gpt4 book ai didi

重新定义默认 SSL 上下文时找不到 Java keystore

转载 作者:太空宇宙 更新时间:2023-11-03 14:14:29 28 4
gpt4 key购买 nike

假设,当遇到不受信任或过期的服务器证书时(就像大多数网络浏览器所做的那样),我希望在我的 Java 应用程序中通过 SSL 的所有连接都请求用户许可。

看起来,最自然的方法是在应用程序启动时替换默认的 SSL 上下文。

这是最小的工作示例:

public class ClientAuthentication {
public static final String SERVER_URL = "https://my.test.server";

public static void main(String[] args) throws Exception {
SSLContext defaultContext = SSLContext.getInstance("TLS");
defaultContext.init(null, new TrustManager[]{new MyX509TrustManager()}, null);
// defaultContext.init(null, null, null);
SSLContext.setDefault(defaultContext);
HttpURLConnection connection = (HttpURLConnection) new URL(SERVER_URL).openConnection();
System.out.println(connection.getResponseCode());
}

private static class MyX509TrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
throw new UnsupportedOperationException("Won't be called by client");
}

@Override
public void checkServerTrusted(X509Certificate[] chain, String s) throws CertificateException {
if (userAcceptsCertificate(chain)) {
System.out.format("Certificate '%s' accepted%n", chain[0].getIssuerX500Principal().getName());
}
}

@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}

private boolean userAcceptsCertificate(X509Certificate[] x509Certificates) {
// ...
return true;
}
}
}

不幸的是,当服务器需要客户端身份验证时,它不起作用。即使通过 -Djavax.net.ssl.keyStore VM 选项正确指定包含客户端证书的 keystore ,连接也会失败javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure,因为根本没有发送客户端证书(在 Wireshark 中跟踪)。

这样的行为有点令人惊讶,因为JavaDoc for SSLContext#init(KeyManager[], TrustManager[], SecureRandom)声明,传递 null 而不是 key 管理器或信任管理器意味着将执行默认查找过程。

反之,如果我传递 null 而不是数组和我的自定义信任管理器作为 init 的第二个参数并指定 JKS 信任库,包含服务器证书,使用
-Djavax.net.ssl.trustStore VM 参数,将在那里找到并成功接受服务器证书

那么,您能否建议一种重新定义默认 SSL 上下文的方法,仅替换信任管理器并保留有关搜索 key 管理器的默认行为?或者可能是找到通过 VM 选项指定的 key 管理器的一些可靠方法。

注意事项

  1. 如果我根本不自定义默认 SSL 上下文,则连接成功,即 VM 选项中的所有路径、密码和存储类型都是正确的。

  2. 我无法以任何方式调用 SSLContext.getDefault()SSLContext.getInstance("Default"),因为默认上下文只能初始化一次。

最佳答案

您已经使用空 key 管理器初始化了上下文。这意味着没有 key 管理器。这并不意味着有默认的 key 管理器。因此,当请求 key 管理器的功能时,什么也不会发生。这些功能包括提供客户端证书。

Javadoc 是错误的。 IBM JSSE 的行为与那里描述的一样,但 Sun/Oracle JSSE 没有,而且从来没有。

关于重新定义默认 SSL 上下文时找不到 Java keystore ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23205266/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com