• 欢迎访问web前端中文站,JavaScript,CSS3,HTML5,web前端demo
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏web前端中文站吧

为什么Java中的密码优先使用 char[] 而不是String?

JAVA web前端中文站 2年前 (2017-05-14) 820次浏览 已收录 0个评论

这个问题在国内很少有人关注,以至于面试时,一问三不知!包括我和我的同事,以及我的多个领导都不清楚其中的原因。今天我终于在 Statck Overflow 上找到了答案。

更多精彩内容请看 web 前端中文站
http://www.lisa33xiaoq.net 可按 Ctrl + D 进行收藏

问题:为什么 Java 中的密码优先使用 char[] 而不是 String?

在 Swing 中,密码字段有一个 getPassword()(返回 char 数组)方法而不是通常的 getText()(返回 String)方法。同样的,我遇到过一个建议,不要使用 String 来处理密码。

为什么 String 涉及到密码时,它就成了一个安全威胁?感觉使用 char 数组不太方便。

问题答案

String 是不可变的。这意味着一旦创建了字符串,如果另一个进程可以进行内存转储,在 GC 发生前,(除了反射)没有方法可以清除字符串数据。

使用数组操作完之后,可以显式地清除数据:可以给数组赋任何值,密码也不会存在系统中,甚至垃圾回收之前也是如此。

所以,是的,这是一个安全问题 – 但是即使使用了 char 数组,仅仅缩小了了攻击者有机会获得密码的窗口,它值针对制定的攻击类型。

简单点说就是为了安全。

虽然 String 加载密码之后可以把这个变量扔掉,但是字符串并不会马上被 GC 回收,一但进程在 GC 执行到这个字符串之前被 dump,dump 出的的转储中就会含有这个明文的字符串。那如果我去“修改”这个字符串,比如把它赋一个新值,那么是不是就没有这个问题了?答案是否定的,因为 String 本身是不可修改的,任何基于 String 的修改函数都是返回一个新的字符串,原有的还会在内存里。对于 char[]来说,你可以在抛弃它之前直接修改掉它里面的内容,密码就不会存在了。但是如果你什么也不做直接交给 gc 的话,也会存在上面一样的问题。

这种做法意义有多大?

如果没有及时清空而由 GC 来清除的话,暴露窗口大约是秒这个数量级,如果能够在计算 HASH 后立即清除,暴露窗口大约是微秒数量级。如此简单的设计就可以降低如此多的被攻击概率,性价比是非常高的。

如何使用反射来修改 String? 和修改 char[] 相比,有何区别和风险?

通过 reflection 机制可以查看 String 的内部的内存成员,从而可以直接修改其中的数据区。但是这样的做法会有问题,内部化的 String 为了提高 HASH 速度,节省空间,值相同的字符串通常只有一个实例。你自己的 char[],修改它是没有副作用的。但是 String 里的 char[],很可能是多个 String 所共享的,你改掉它就会殃及别的 String。举个例子,有一个密码是"Password",而你密码框提示密码输入的文字也是"Password",改掉第一个"Password"会把后面那个也改掉。

如果一点明文也不想出现,应该怎么做?

为了保证“全部处理流程均无明文密码”,需要底层 API 在给你密码之前就做了 HASH,并且这个 HASH 算法就是你想要的那种。最好还加盐。不过这只是在用户程序方面无明文,底层获取中会不会有明文就保证不了了。

有没有绝对安全策略?

安全往往是相对于攻击成本而言的,攻击收益越高,黑客就越能接受攻击成本高的方案。因此,你采取的安全策略应该与这个攻击收益相匹配。对于极其敏感和宝贵的数据来源,就需要在安全方面上下很大功夫。目前来看,没有绝对的安全,只有相对的安全。

【注:本文源自网络文章资源,由站长整理发布】


web 前端中文站 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:为什么 Java 中的密码优先使用 char[] 而不是 String?
喜欢 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址