Setting a client certificate as a request property in a Java HTTP connection?

前端 未结 1 950
南方客
南方客 2021-01-07 15:23

I have a Java application that connects to another Java app through a socket with SSL, so my client JVM already has the -Djavax.net.ssl.keyStore and -Djav

1条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-01-07 15:55

    Setting a SSL "client certificate" is not adequate directly through HTTPSURLConnectionImpl's request properties, because a digital signature is also required to prove you own the certificate. SSL already does all that automatically, so to makes sense to use that layer.

    You have two ways to solve your issue going forward.

    Through configuration

    You can add you client key and certificate to your JVM KeyStore, it should be picked up at Runtime when the server asks for your client-side SSL authentication. (SSL/TLS is designed for that : the server will ask for a client certificate that is signed by it's trusted authority, which allows the SSL Engine to choose the right certificate, even when your KeyStore holds many).

    Through Code

    You can roll you own SSLContext using custom made KeyStore/TrustStores. This is a bit complex (I won't elaborate on how to build Keystore instances in Java), but the gist of it is here :

    public static void main(String[] args) throws Exception {
    
    KeyStore clientKeyStore = ... // Whatever
    KeyStore clientTrustStore = ... // Whatever you need to load
    
    // We build the KeyManager (SSL client credentials we can send)
    KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    keyFactory.init(clientKeyStore, "password".toCharArray());
    KeyManager[] km = keyFactory.getKeyManagers();
    
    // We build the TrustManager (Server certificates we trust)
    TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustFactory.init(clientTrustStore);
    TrustManager[] tm = trustFactory.getTrustManagers();
    
    // We build a SSLContext with both our trust/key managers
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(km, tm, null);
    SSLSocketFactory sslSf = sslContext.getSocketFactory();
    
    // We prepare a URLConnection 
    URL url = new URL("https://www.google.com");
    URLConnection urlConnection = url.openConnection();
    // Before actually opening the sockets, we affect the SSLSocketFactory
    HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) urlConnection;
    httpsUrlConnection.setSSLSocketFactory(sslSf);
    
    // Ready to go !
    }
    

    0 讨论(0)
提交回复
热议问题