在 Java 中存储密码的最佳方法是什么

在本文中,我们将解释为什么我们应该使用 char[] 数组来表示密码,而不是 Java 中的字符串。

请注意,本教程重点介绍在内存中操作密码的方法,而不是存储密码的实际方法,后者通常在持久层中处理。

我们还假设我们无法控制密码的格式(例如,密码以字符串的形式来自第三方 API)。虽然使用 java.lang.String 类型的对象来操作密码似乎很明显,但 Java 团队自己建议使用 char[] 代替。

例如,如果我们看一下javax.swing的JPasswordField,我们可以看到返回String的方法getText()自Java 2以来被弃用,取而代之的是返回char[]的getPassword()方法。

字符串是不可变的

Java 中的字符串是不可变的,这意味着我们不能使用任何高级 API 更改它们。对 String 对象的任何更改都将生成一个新的字符串,并将旧字符串保留在内存中。

因此,存储在字符串中的密码将在内存中可用,直到垃圾回收器清除它。我们无法控制它何时发生,但这个时间段可能比常规对象长得多,因为字符串保存在字符串池中以实现可重用性。

因此,有权访问内存转储的任何人都可以从内存中检索密码。

使用 char[] 数组而不是 String,我们可以在完成预期工作后显式擦除数据。这样,我们将确保甚至在进行垃圾回收之前就从内存中删除密码。

现在让我们看一下代码片段,它们演示了我们刚刚讨论的内容。

第一个字符串:

System.out.print("Original String password value: ");
System.out.println(stringPassword);
System.out.println("Original String password hashCode: "
  + Integer.toHexString(stringPassword.hashCode()));

String newString = "********";
stringPassword.replace(stringPassword, newString);

System.out.print("String password value after trying to replace it: ");
System.out.println(stringPassword);
System.out.println(
  "hashCode after trying to replace the original String: "
  + Integer.toHexString(stringPassword.hashCode()));

输出将是:

Original String password value: password
Original String password hashCode: 4889ba9b
String value after trying to replace it: password
hashCode after trying to replace the original String: 4889ba9b

现在对于字符[]:

char[] charPassword = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};

System.out.print("Original char password value: ");
System.out.println(charPassword);
System.out.println(
  "Original char password hashCode: " 
  + Integer.toHexString(charPassword.hashCode()));

Arrays.fill(charPassword, '*');

System.out.print("Changed char password value: ");
System.out.println(charPassword);
System.out.println(
  "Changed char password hashCode: " 
  + Integer.toHexString(charPassword.hashCode()));

输出为:

Original char password value: password
Original char password hashCode: 7cc355be
Changed char password value: ********
Changed char password hashCode: 7cc355be

正如我们所看到的,在我们尝试替换原始 String 的内容后,值保持不变,hashCode() 方法在应用程序的相同执行中没有返回不同的值,这意味着原始字符串保持不变。

对于 char[] 数组,我们能够更改同一对象中的数据。

我们可能会意外打印密码

在 char[] 数组中使用密码的另一个好处是防止在控制台、显示器或其他或多或少不安全的地方意外记录密码。

让我们看看下一个代码:

String passwordString = "password";
char[] passwordArray = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};
System.out.println("Printing String password -> " + passwordString);
System.out.println("Printing char[] password -> " + passwordArray);

使用输出:

Printing String password -> password
Printing char[] password -> [C@6e8cf4c6

我们看到内容本身在第一种情况下是打印的,而在第二种情况下,数据不是那么有用,这使得 char[] 不那么容易受到攻击。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值