I used CXF to set up a client for a SSL-secured web service. I set the environment variables for truststore and keystore as ususal:
System.setProperty("javax.net.ssl.trustStore", "truststore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "secret");
System.setProperty("javax.net.ssl.keyStore", "keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "secret");This works out-of the-box with a simple Java SSL client. No other configuration is needed to authenticate with client certificates.
But not with CXF. The server side complained about "bad_certificate" and "certificate chain null" regardless on how I set up the keystore and truststore. A rather annoying day of CXF core code debugging followed until I found the solution: CXF needs the key and truststore explicitly set using the appropriate factories! It does not work with only the properties set, it does not work with user created trustmanagers and keymanagers! You have to exactly follow the example found in this article. Otherwise, CXF does not recognize the certificates right and simply do not send them to the server side, leaving the certificate chain empty.
More annoying is that you need both ways of setting the keystore and truststore: it also does not work without specifying the environment variables! So the resulting code example is like this:
System.setProperty("javax.net.ssl.trustStore", "truststore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "secret");
System.setProperty("javax.net.ssl.keyStore", "keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "secret");
Client client = ClientProxy.getClient(caPort);
HTTPConduit conduit = (HTTPConduit)client.getConduit();
TLSClientParameters tlsParams = new TLSClientParameters();
// disabling host name check
tlsParams.setDisableCNCheck(true);
// setup truststore - AGAIN!
KeyStore keyStore = KeyStore.getInstance("JKS");
String trustpass = "secret";
File truststore = new File("truststore.jks");
keyStore.load(new FileInputStream(truststore), trustpass.toCharArray());
// setting trust manager(s)
TrustManagerFactory trustFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(keyStore);
TrustManager[] tm = trustFactory.getTrustManagers();
tlsParams.setTrustManagers(tm);
// setup keystore - AGAIN!
truststore = new File("keystore.jks");
keyStore.load(new FileInputStream(truststore), trustpass.toCharArray());
// setting up key manager(s)
KeyManagerFactory keyFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, trustpass.toCharArray());
KeyManager[] km = keyFactory.getKeyManagers();
tlsParams.setKeyManagers(km);
// setting parameters
conduit.setTlsClientParameters(tlsParams); CXF is great, but sometimes, I'm getting real old with it..
Keine Kommentare:
Kommentar veröffentlichen