SSL连接问题-未发送必需的SSL证书

时间:2019-08-11 21:12:41

标签: java ssl okhttp3

我拥有客户端证书和CA证书,并且按照本教程进行操作以生成相应的p12文件和jks文件。

我运行了以下命令来生成上述文件:

openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -name "pandb_client"->这给了我client.p12文件

keytool -genkey -dname "cn=CLIENT" -alias storekey -keyalg RSA -keystore ./store.jks -keypass changeit -storepass changeit->这给了我store.jks

keytool -import -keystore ./store.jks -file ca.crt -alias client->我将CA导入到新创建的JKS中

代码如下:

import okhttp3.*;
import org.apache.http.ssl.SSLContexts;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.*;
import java.security.cert.CertificateException;
import java.time.Duration;


final class ConnectUsingSSL {
    private static final String CA_KEYSTORE_TYPE = KeyStore.getDefaultType(); //"JKS";
    private static final String CA_KEYSTORE_PATH = "store.jks";
    private static final String CA_KEYSTORE_PASS = "changeit";
    private static final String CLIENT_KEYSTORE_TYPE = "PKCS12";
    private static final String CLIENT_KEYSTORE_PATH = "client.p12";
    private static final String CLIENT_KEYSTORE_PASS = "changeit";

    public static void main(String[] args) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, KeyManagementException, UnrecoverableKeyException {

        SSLContext context = createSslCustomContext();
        final OkHttpClient okHttpClient = new OkHttpClient.Builder().
                readTimeout(Duration.ofMillis(60000L)).
                connectTimeout(Duration.ofMillis(60000L)).
                callTimeout(Duration.ofMillis(60000L)).
                retryOnConnectionFailure(Boolean.TRUE).
                sslSocketFactory(context.getSocketFactory(), (X509TrustManager) getTrustManager()[0]).
                hostnameVerifier((hostname, session) -> true).
                build();
        RequestBody requestBody = RequestBody.create("{\"query\": {\"urls\": [\"google.com\", \"yahoo.com\", \"facebook.com\"]}}",
                MediaType.parse("application/json; charset=utf-8"));

        Request request = new Request.Builder().
                url("https://somehost:443/query_urls").
                post(requestBody).
                build();
        try (Response response = okHttpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response.body().string());
            System.out.println(response.body().string());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static SSLContext createSslCustomContext() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException {
        // Trusted CA keystore
        KeyStore tks = KeyStore.getInstance(CA_KEYSTORE_TYPE);
        tks.load(new FileInputStream(CA_KEYSTORE_PATH), CA_KEYSTORE_PASS.toCharArray());

        // Client keystore
        KeyStore cks = KeyStore.getInstance(CLIENT_KEYSTORE_TYPE);
        cks.load(new FileInputStream(CLIENT_KEYSTORE_PATH), CLIENT_KEYSTORE_PASS.toCharArray());

        return SSLContexts.custom()
                .loadKeyMaterial(cks, CLIENT_KEYSTORE_PASS.toCharArray())
                .build();
    }

    private static TrustManager[] getTrustManager() throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
        // Trusted CA keystore
        KeyStore tks = KeyStore.getInstance(CA_KEYSTORE_TYPE);
        tks.load(new FileInputStream(CA_KEYSTORE_PATH), CA_KEYSTORE_PASS.toCharArray());
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(tks);
        return tmf.getTrustManagers();
    }

}

我花了7个多小时来尝试完成这项工作,但是我未能提供任何帮助,我们深表感谢。

来自服务器的响应:

java.io.IOException: Unexpected code <html>
<head><title>400 No required SSL certificate was sent</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>nginx/1.12.2</center>
</body>
</html>

导入套接字 导入ssl

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.SSLSocket(sock=s, ssl_version=ssl.PROTOCOL_TLSv1,
                      certfile="client.crt", keyfile="client.key",
                      server_hostname="queryurls")
ssl_sock.connect(("somehost", 443))
body = '{"query": {"urls": ["google.com", "yahoo.com", "facebook.com"]}}'
rqst = "POST /query_urls HTTP/1.1\r\nHost: queryurls\r\nContent-Type: application/json\r\nContent-Length: %d\r\nConnection: keep-alive\r\n\r\n%s" % (len(body), body)
ssl_sock.sendall(rqst)
#you should process the HTTP reply header to retrieve the reply body length
#and keep reading until you receive the full reply body.
print rqst
reply = ssl_sock.recv(16384);
print reply

当我运行上面的Python代码时,相同的客户端证书和CA可以很好地工作,不确定如何在JAVA中复制它。

0 个答案:

没有答案