Choosing SSL client certificate in Java

后端 未结 3 1589
名媛妹妹
名媛妹妹 2020-11-28 08:52

Our system communicates with several web services providers. They are all invoked from a single Java client application. All the web services up until now have been over SSL

相关标签:
3条回答
  • 2020-11-28 09:17

    I initialized EasySSLProtocolSocketFactory and Protocol instances for different endpoints and register the protocol with unique key like this:

    /**
     * This method does the following:
     * 1. Creates a new and unique protocol for each SSL URL that is secured by client certificate
     * 2. Bind keyStore related information to this protocol
     * 3. Registers it with HTTP Protocol object 
     * 4. Stores the local reference for this custom protocol for use during furture collect calls
     * 
     *  @throws Exception
     */
    public void registerProtocolCertificate() throws Exception {
        EasySSLProtocolSocketFactory easySSLPSFactory = new EasySSLProtocolSocketFactory();
        easySSLPSFactory.setKeyMaterial(createKeyMaterial());
        myProtocolPrefix = (HTTPS_PROTOCOL + uniqueCounter.incrementAndGet());
        Protocol httpsProtocol = new Protocol(myProtocolPrefix,(ProtocolSocketFactory) easySSLPSFactory, port);
        Protocol.registerProtocol(myProtocolPrefix, httpsProtocol);
        log.trace("Protocol [ "+myProtocolPrefix+" ] registered for the first time");
    }
    
    /**
     * Load keystore for CLIENT-CERT protected endpoints
     */
    private KeyMaterial createKeyMaterial() throws GeneralSecurityException, Exception  {
        KeyMaterial km = null;
        char[] password = keyStorePassphrase.toCharArray();
        File f = new File(keyStoreLocation);
        if (f.exists()) {
            try {
                km = new KeyMaterial(keyStoreLocation, password);
                log.trace("Keystore location is: " + keyStoreLocation + "");
            } catch (GeneralSecurityException gse) {
                if (logErrors){
                    log.error("Exception occured while loading keystore from the following location: "+keyStoreLocation, gse);
                    throw gse;
                }
            }
        } else {
            log.error("Unable to load Keystore from the following location: " + keyStoreLocation );
            throw new CollectorInitException("Unable to load Keystore from the following location: " + keyStoreLocation);
        }
        return km;
    }   
    

    When I have to invoke the web service, I do this (which basically replace "https" in the URL with https1, or https2 or something else depending on the Protocol you initialized for that particular endpoint):

    httpClient.getHostConfiguration().setHost(host, port,Protocol.getProtocol(myProtocolPrefix));
    initializeHttpMethod(this.url.toString().replace(HTTPS_PROTOCOL, myProtocolPrefix));
    

    It works like a charm!

    0 讨论(0)
  • 2020-11-28 09:19

    Java SSL clients will only send a certificate if requested by the server. A server can send an optional hint about what certificates it will accept; this will help a client choose a single certificate if it has multiple.

    Normally, a new SSLContext is created with a specific client certificate, and Socket instances are created from a factory obtained from that context. Unfortunately, Axis2 doesn't appear to support the use of an SSLContext or a custom SocketFactory. Its client certificate settings are global.

    0 讨论(0)
  • 2020-11-28 09:26

    The configuration is done via an SSLContext, which is effectively a factory for the SSLSocketFactory (or SSLEngine). By default, this will be configured from the javax.net.ssl.* properties. In addition, when a server requests a certificate, it sends a TLS/SSL CertificateRequest message that contains a list of CA's distinguished names that it's willing to accept. Although this list is strictly speaking only indicative (i.e. servers could accept certs from issuers not in the list or could refuse valid certs from CAs in the list), it usually works this way.

    By default, the certificate chooser in the X509KeyManager configured within the SSLContext (again you normally don't have to worry about it), will pick one of the certificates that has been issued by one in the list (or can be chained to an issuer there). That list is the issuers parameter in X509KeyManager.chooseClientAlias (the alias is the alias name for the cert you want to picked, as referred to within the keystore). If you have multiple candidates, you can also use the socket parameter, which will get you the peer's IP address if that helps making a choice.

    If this helps, you may find using jSSLutils (and its wrapper) for the configuration of your SSLContext (these are mainly helper classes to build SSLContexts). (Note that this example is for choosing the server-side alias, but it can be adapted, the source code is available.)

    Once you've done this, you should look for the documentation regarding the axis.socketSecureFactorysystem property in Axis (and SecureSocketFactory). If you look at the Axis source code, it shouldn't be too difficult to build a org.apache.axis.components.net.SunJSSESocketFactory that's initialized from the SSLContext of your choice (see this question).

    Just realized you were talking about Axis2, where the SecureSocketFactory seems to have disappeared. You might be able to find a workaround using the default SSLContext, but this will affect your entire application (which isn't great). If you use a X509KeyManagerWrapper of jSSLutils, you might be able to use the default X509KeyManager and treat only certain hosts as an exception. (This is not an ideal situation, I'm not sure how to use a custom SSLContext/SSLSocketFactory in Axis 2.)

    Alternatively, according to this Axis 2 document, it looks like Axis 2 uses Apache HTTP Client 3.x:

    If you want to perform SSL client authentication (2-way SSL), you may use the Protocol.registerProtocol feature of HttpClient. You can overwrite the "https" protocol, or use a different protocol for your SSL client authentication communications if you don't want to mess with regular https. Find more information at http://jakarta.apache.org/commons/httpclient/sslguide.html

    In this case, the SslContextedSecureProtocolSocketFactory should help you configure an SSLContext.

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