开发工具分享
  • 首页
  • 计算科学
  • 文化旅游
  • 项目和网站
    • OSSEZ 计算技术
    • USRealEstate 社区
    • 地区文化
    • CWIKI.US
    • BUG.OSSEZ.COM
    • RSS.OSSEZ.COM
CWIKIUS.CN
一个有独立思考和温度的清新站
  1. Home
  2. Computer Science
  3. This article

Java 使用 char[] Array 还是 String 存储字符串密码

2022年08月03日 359Browse 0Like 0Comments

概述

在本文章中,我们主要用来说明为什么应该使用 char[] 数组来存储密码,而不是使用 String 来存储密码。

需要注意的是,为了密码的安全,我们通常都会将用户输入的密码 MD5 加密哈希后进行存储。

我们通常是不会在后台中存储明文的用户密码的,这篇文章主要目的就是为了说明字符串在 Java 中的存储方式和在存储中的实现,就算你应该使用 char[] 数组来存储,你也不应该在程序中使用明文。

同时,本文章还假设你没有办法对 String 字符串进行控制。例如你获得密码是从某些第三方工具上面获得的,或者第三方 API 传递过来的,通常你是没有办法对上面的字符串进行控制的。

因此,你还不得不使用 java.lang.String 对象来对密码进行实现,经过 Java 的官方小组还是推荐使用 char[] 数组来实现。

你可以通过单击 JPasswordField 这个链接来查看 JPasswordField API 的使用,这个 API 是存在 javax.swing 包中的。

我们可以知道 getText() 这个返回 String 的方法从 Java 2 开始就被丢弃了,你应该使用 getPassword() 来返回密码,这个方法实际上是返回的 char[] 字符串。

 

java-password-01

 

下面来让我们看看为什么应该使用 char[] 数组来存储密码了。

Strings 是不可变的(Immutable)

String 在 Java 中是不可变的。这个不可变的意思是,String 是不能被更高一级的 API 进行操作的。

任何对 String 对象的修改都会创建一个新的 String 对象,同时将老的 String 对象保存在内存中。

上面这句话的意思就是:如果密码(Password)使用 String 来进行存储的话,如果你对密码进行操作后,老的密码还是在内存中存在的,知道 Java 的垃圾回收程序来清理掉。

这个垃圾回收的过程,我们是没有办法进行控制的,我们也不知道 JVM 什么时候执行垃圾清理。这个清理的过程与其他对象的清理对比来说,可能需要等待比较长的时间。这是因为 String 在 JVM 中是存储在 String Pool 中的,这个主要是为了便于对 String 的再次利用。

因为有这个缓存的存在,所以 String 在内存中保留的时间会比较长。

在这个过程中,任何人如果对 JVM 进行 Dump 内存操作的话,任何人都可以从内存中获得密码的明文。

如果我们使用 char[] 数组来存储密码的话,我们可以在对密码的计算完成后来使用程序对数组进行清理。因此,我们可以保证我们使用过的密码从内存中完全清楚,而不是等候 JVM 垃圾清理程序来进行清理。

下面我们来看代码来对上面的用例进行说明:

String 测试

    @Test
    public void immutableForString() {
        String stringPassword = "password";
        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 password value after trying to replace it: password
hashCode after trying to replace the original String: 4889ba9b

char 数组测试

    @Test
    public void immutableForCharArray() {
        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: 10d59286
Changed char password value: ********
Changed char password hashCode: 10d59286

 

java_string_array

 

正如我们所看到的那样,当我们对 String 进行了操作后,操作后的结果是不会改变原始输入 String 的结果的。

我们可以看到上面的代码,hashCode() 方法返回的结果是一样的,并没有给我们有不同的结果,同时 String 中的值也保持一致。

使用 char[] 数组的时候,我们注意到,hashCode() 的值是一样的,但是内容却不一样了。这是因为我们对 char[] 进行了操作所导致的,我们可以对相同的对象中的数据进行修改。

需要注意 stringPassword.replace(stringPassword, newString); 方法,如果你需要获得这个方法替换后的值得话,你需要将方法执行后的值重新赋值才可以。

避免意外打印密码

使用 char[] 数组来存储密码的好处就是能够避免意外的将内存中存储的密码数据输出到控制台,显示器或者其他并不安全的地方。

让我们来考察下面的代码:

    @Test
    public void accidentallyPassword_print() {
        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@2698dc7

我们可以从上面的输出了解到,String 的输出是完整的内容输出,char[] 的输出不是将 char[] 中的内容输出,这样的方式让输出更不容易泄密。

这是因为在 Char 数组打印的时候调用的是一个 toString 的方法,这个方法输出的是类的值和类的哈希代码(hashCode)转换成 16 进制。

这就是你看到这一串奇怪字符串的原因。

结论

在这篇文章中,我们对为什么应该使用 char 数组而不是使用 String 来存储密码或者敏感字符串的原因进行了说明。

同时通过举例来说明了一些相关问题和结构。

 

https://www.ossez.com/t/java-char-array-string/14015

Tags: None
Last updated:2022年08月03日

HoneyMoose

有温度的人文和独立的思考

Like
< Previous
Next >

Comments

Cancel reply

Archives
  • May 2026
  • April 2026
  • March 2026
  • February 2026
  • January 2026
  • December 2025
  • November 2025
  • October 2025
  • September 2025
  • August 2025
  • July 2025
  • June 2025
  • May 2025
  • April 2025
  • March 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • October 2024
  • September 2024
  • August 2024
  • July 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • May 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • August 2021
  • July 2021
  • June 2021
  • May 2021
  • April 2021
  • March 2021
  • February 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • April 2020
  • March 2020
  • February 2020
  • January 2020
  • December 2019
  • November 2019
  • October 2019
  • September 2019
  • August 2019
  • July 2019
  • June 2019
  • May 2019
  • April 2019
  • March 2019
  • February 2019
  • January 2019
  • December 2018
  • November 2018
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • June 2018
  • May 2018
  • April 2018
  • March 2018
Categories
  • Computer Science (2,362)
    • Confluence (663)
    • Gradle (12)
  • U.S. (482)
  • 文化旅游 (145)

COPYRIGHT © 2020 CWIKIUS. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS

湘ICP备2020018253号-1