【问题标题】:Client authentication with HttpClient使用 HttpClient 进行客户端身份验证
【发布时间】:2016-02-06 12:01:27
【问题描述】:

尝试实现客户端密钥身份验证(使用自签名 ca)。

代码如下:

KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("client.p12"), "changeit".toCharArray())

SSLContext sslcontext = SSLContexts.custom()
            .loadTrustMaterial(null, new TrustSelfSignedStrategy()) //DONT DO THAT, IT'S JUST TO SIMPLIFY THIS EXAMPLE. USE REAL TrustStore WITH REAL SERVER CERTIFICATE IMPORTED. DONT TRUST SELF SIGNED
            .loadKeyMaterial(keyStore, "changeit".toCharArray())
            .build();
socketFactory = new SSLConnectionSocketFactory(
            sslcontext,
            new String[] {"TLSv1.2", "TLSv1.1"},
            null,
            new NoopHostnameVerifier()
);
HttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(socketFactory)
            .build();

使用-Djavax.net.debug=all 我可以看到它正确地选择了我的证书,我看到了签名,我看到了证书请求,还有 ECDHClientKeyExchange 等等,一切看起来都很好。

但无论如何我都收到了来自 Nginx 的以下响应(状态为 400):

<head><title>400 The SSL certificate error</title></head>

注意,对于不正确的证书/密钥,nginx 通常会丢弃会话,而不会在纯文本响应中提供任何详细信息。

这个client.p12 在命令行下工作,例如:

$ curl -ivk --cert client.p12:changeit https://192.168.1.1


* Rebuilt URL to: https://192.168.1.1/
*   Trying 192.168.1.1...
* Connected to 192.168.1.1 (192.168.1.1) port 443 (#0)
* WARNING: SSL: Certificate type not set, assuming PKCS#12 format.
* Client certificate: client-es.certs.my
* TLS 1.2 connection using TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
* Server certificate: server.certs.my
* Server certificate: ca.my
> GET / HTTP/1.1
> Host: 192.168.1.1
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK

所以这个密钥肯定是有效的。但为什么它不适用于 Java? java ssl config中有什么我遗漏的吗?

【问题讨论】:

  • 您的证书是否已导入您的密钥库?
  • 直接从client.p12加载。我也尝试将它导入密钥库,但它并没有改变任何东西

标签: java ssl nginx


【解决方案1】:

问题是我的客户端密钥还包括密钥链中的签名证书。不仅是我的客户端证书(这是身份验证所必需的),还有整个证书链(当然没有密钥,只有证书)

原来是:

> Root CA cert -> Client CA cert -> Client key + cert

我猜在这种情况下 Java 使用了错误的证书,可能是 CA 或中间证书。

通过添加到p12keychain 仅客户端的密钥和证书,没有中间体。

不应该-certfile 选项(我以前有)。只是客户端密钥/证书。正确的导出命令是:

openssl pkcs12 -export \
    -in client.crt -inkey client.key \
    -out client.p12

这个client.p12 然后可以导入钥匙串:

keytool -importkeystore \
    -deststorepass changeit -destkeystore keystore \
    -srckeystore client.p12 -srcstoretype PKCS12 -srcstorepass changeit

并且对于自定义身份验证工作得很好。

【讨论】:

  • 我认为这与 NGINX 有关。我们有 F5 和 NGINX。我们只需要进行此更改即可与 NGINX 通信。我想了解我可以对 NGINX 进行哪些更改来修复它,而不是更改我的证书。
猜你喜欢
  • 1970-01-01
  • 2014-05-01
  • 2012-01-10
  • 2022-10-30
  • 2015-10-29
  • 2018-07-05
  • 2019-01-14
  • 2013-06-06
  • 2012-04-24
相关资源
最近更新 更多