在 Java 中,如何在不生成 String 对象的情况下从 HttpServletRequest 标头中提取密码?

处理敏感数据(== 密码)的通用 Java 安全指南建议不要使用 String 对象来存储数据,而是使用字节或字符数组.我正在尝试在 HttpServlet 处理程序中应用此指南.特别是,我使用了一种类似基本身份验证的方法,其中凭据在标头中传递(这是一个 GET 请求,所以没有正文).

A common Java security guideline for handling sensitive data (== passwords) recommends never using a String object to store the data, and instead using an array of bytes or chars. I am trying to apply this guideline in a HttpServlet handler. In particular, I am using a basic-authentication-like approach where the credentials are passed in in a header (this is a GET request, so no body).

我遇到的问题是,在不生成 String 对象的情况下似乎无法获取标头数据,这违反了从一开始就制定的准则.我已经非常彻底地搜索了一个解决方案,但没有找到任何相关的讨论.有人对这个问题有任何见解吗?

The issue I'm running into is that it seems impossible to get to the header data without generating a String object, which violates the guideline from the get-go. I've searched for a solution pretty thoroughly, and didn't find any relevant discussion. Does anybody have any insight into this issue?

注意:这是通过 HTTPS 进行的,因此这里不存在连接安全问题.

NOTE: this takes place over HTTPS, so there is no connection security problem here.

推荐答案

简单的回答是,除了String之外,你无法获取任何其他形式的参数.至少,不使用标准的 servlet API.但是有几个可能的退出".

The simple answer is that you can't get the parameter in any other form than a String. At least, not using the standard servlet APIs. But there are a couple of possible "get outs".

  1. 如果你准备变得非常丑陋,你实际上可以打破 String 对象的抽象,并覆盖并覆盖字符.(如果您准备打破规则,字符串实际上是可变的.这是少数情况下可以证明这一点的情况之一.)

  1. If you are prepared to get really ugly, you can in fact break the abstraction of the String object, and reach in and overwrite the characters. (Strings are in fact mutable if you are prepared to break the rules. This is one of the few situations where this might be justified.)

在您的 Web 容器的(比如说)HttpServletRequest 的实现中可能有一个非标准的 API 扩展来执行此操作.如果没有,您可以获取源代码并添加一个.(假设您使用的是开源 Web 容器.)

There might be a nonstandard API extension in your web container's implementation of (say) HttpServletRequest for doing this. If not, you may be able to get hold of the source code and add one. (Assuming you are using an open-source web container.)

<小时>

话虽如此,IMO 对 Java 安全性的无条件"方法是错误的,或者至少在其实现的目标方面被高估了.


Having said that, IMO the "no strings" approach to Java security is misguided, or at least over-rated in terms of what it achieves.

无字符串"方法可防止某些东西在您的应用程序的地址空间中进行拖网,找到看起来像字符串的东西,并嗅出可能的密码.理论上,这可以通过以下方式完成:

The "no strings" approach guards against the possibility that something can trawl through the address space of your application, locate things that look like strings, and sniff out possible passwords. In theory, this could be done by:

  • 一种破坏 JVM 执行模型并查看原始内存的 hack,
  • 附加一个 Java 调试器并搜索可访问的对象,
  • 使用/dev/mem"或类似的方式从外部读取进程内存,
  • 访问硬盘上程序交换映像的剩余部分,或
  • 不知何故导致它进行核心转储并读取转储.

但是,除了第一个之外,所有这些都要求坏人已经破坏了系统的安全性.如果坏人这样做了,还有其他(可能更简单)的方法可以从您的程序中窃取密码……无字符串"方法无法阻止.

However, all but the first of these requires that the bad guy has already broken security on the system. And if the bad guy has done that there are other (probably simpler) ways to steal passwords from your program ... which the "no strings" approach won't prevent.

如果您担心利用 Java 安全漏洞读取原始内存的黑客攻击,那么该漏洞可能会以其他方式使用;例如注入代码以改变代码处理密码的方式.

And if you are worried about a hack that exploits a Java security flaw to read raw memory, that flaw could probably used in other ways; e.g. to inject code to alter the way that the passwords are handled by the code.

因此,总而言之,无条件"可以防止非常困难的黑客攻击,或者防止您的安全已经被破坏的情况.IMO,不值得付出努力......除非您要求实施军事级安全.

So in summary, "no strings" is protecting against either really difficult hacks, or against cases where your security is already blown. IMO, it is not worth the effort ... unless you are required to implement military grade security.

相关文章