在不将凭据作为字符串传递的情况下使用 Apache HTTP 客户端?

Using Apache HTTP Client without passing the credentials as String?

在对我们的 Swing 应用程序进行审核后,我们的用户的某些密码似乎在登录甚至注销后很长时间内仍保留在内存中。

原因之一似乎是 Apache HttpClient 的 UsernamePasswordCredentials stores the password as a final String, preventing to programmatically wipe it from memory (see Why is char[] preferred over String for passwords?).

然而,由于它实现的 Credentials 接口有一个 String getPassword() 方法,似乎无法在某些时候避免转换为 String

在这种情况下,还有其他方法可以避免将密码作为 String 传递吗?

我们使用的是 HttpClient 4.0.3,但在最近的版本中似乎没有变化。

Apache 表示不推荐使用密码字符串初始化 UsernamePasswordCredentials

UsernamePasswordCredentials(String usernamePassword)
Deprecated.
(4.5) will be replaced with String, char[] in 5.0

UsernamePasswordCredentials(String userName, String password)
The constructor with the username and password arguments.

https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/auth/UsernamePasswordCredentials.html

您使用的是最新版本的库吗?如果是这样,他们就不会将密码存储为字符串,而是存储为 char[]。

最后我实施了解决方法

char[] password = …
final Credentials credentials = new UsernamePasswordCredentials(username, null) {
    @Override
    public String getPassword() {
        // AKCTAT-3791: this helps the GC to clear the String from the memory, as it will be used and dismissed immediately
        // Unfortunately Apache HTTP Client does not allow to pass the byte[] directly
        return new String(password);
    }
};
httpClient.getCredentialsProvider().setCredentials(ANY_AUTHSCOPE, (Credentials) auth.getCredentials());
// ... (do stuff with httpClient)
Arrays.fill(password, '[=10=]');

看起来 GC 很快就将其从内存中删除了,但这仍然只是一种无法保证的解决方法。