在Java中将String设置为null是一种好的实践吗?

15

我在存储明文密码的字符串时遇到了问题。根据参考资料,由于字符串是不可变的,因此在内存中使用字符串数据类型来存储敏感数据存在漏洞。

https://www.geeksforgeeks.org/use-char-array-string-storing-passwords-java/

为什么char[]比String更适合用于密码?

我能否通过将字符串变量设置为null来解决这个安全问题,而不是使用char数组或String缓冲区/构建器。

例如:String password = "password"; password = null;


1
您的密码应该是一个字符数组。 - ΦXocę 웃 Пepeúpa ツ
1
使用字节数组? - Lyju I Edwinson
1
你不能通过将字符串变量赋值为null来解决问题,因为它不会将字符串对象从字符串常量池中移除,你只是将'password'赋值为null,而不是从内存中删除实际的密码。 - DhaRmvEEr siNgh
1
将字符串置空肯定有助于解决内存泄漏问题,但是该字符串仍然存在于Java字符串池中。尽管您无法访问字符串池,因为它由Java私下维护。最好使用字节数组或字符数组,并在需要使事情更加安全时应用适当的加密。 - Amit Kumar Lal
2个回答

11

将字符串设为null只是取消了其引用,但该值仍会存在于字符串池中,因为为了节约内存,字符串值会保留在字符串池中。

任何潜在的黑客都可以通过访问字符串池来检索值。

而使用char[],您可以将该对象简单地视为任何其他对象。将char对象设置为null将在垃圾收集时从堆中清除数据。

更好的选择是使用字节数组。

阅读有关字符串常量池的更多信息。


谢谢您的回答。但我还有另一个疑虑:如果我们在将对象置空后强制调用垃圾收集器,它是否会仍然留在内存中? - Sudesh Chandana
2
是的。垃圾收集器在字符串池上运行的方式与其他对象不同。请参见 https://dev59.com/EGMl5IYBdhLWcg3wbGl1#18407081 以获得更多理解。 - tryingToLearn
3
如果一个值是字面常量或者已经被 intern(),那么它才会被放入字符串池中。这更多地是关于控制密码在内存中的生命周期。使用 char[] 的建议是正确的,但是需要在使用后将其清空,仅将其设置为 null 是不够的。 - Kayaman

3
如果你想要绝对的安全性,不要将字符串置空。这样做的原因是,将其置空并不能保证该字符串不再可用。虽然这可能会使其更容易被垃圾回收(仅限于“可能”),但没有关于何时甚至是否进行垃圾回收的保证。在结束时,应使用字节数组或字符数组,并将数组中的每个元素置空。

尽管这可能会增加垃圾回收的可能性(这只是“可能”),但不能保证何时(甚至是否)进行垃圾回收。在将对象置空后,如果我们强制调用垃圾收集器,它是否仍然会留在内存中? - Sudesh Chandana
1
@Sudesh 你不能强制进行垃圾回收。(System.gc()仅仅是暗示你想要进行GC,但并不保证它会真正执行任何操作)。 - Andy Turner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接