This is a simple example that will show you how to write a Web Service Client to invoke a SSL Secured Web Service. This example uses helloWSDL example to provide the service implementation. Please look at helloWSDL example for how to deploy the service. In this example we will set a Client Certificate Chain for client authentication by the server. Please note that the certificate provided as part of the example may not work against the Application Server you are using. You may need another certificate and private key so that the Application Server you are using, can authenticate it. Please look into your Application Server documentation for more details.1 Implementing the SSLClient
As part of the example, a Certificate Chain(clientCert.chain) in DER format and a PKCS8 Private Key(clientKey.pkcs8) is provided. The example shows various ways to set the same property. The 2 methods for setSSLProperties show how to set SSL properties in different ways. The first one sets the certificate chain as byte[][] and the second one as java.security.X509Certificate[]. Similarly other properties are also set on the stub. Please look at com.sssw.jbroker.web.security.SSLProperties interface to know which SSL properties are available for SSL configuration.package sslHello; import java.io.*; import java.util.*; import java.util.jar.JarFile; import java.util.jar.JarEntry; import javax.xml.rpc.Stub; import javax.naming.InitialContext; import java.security.cert.X509Certificate; import java.security.cert.CertificateFactory; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import com.sssw.jbroker.web.security.SSLProperties; import helloWSDL.*; public class SSLClient { public static void main(String[] args) throws Exception { | // get the initial context | InitialContext ctx = new InitialContext(); | | // lookup the service for Hello | HelloService svc = (HelloService) | ctx.lookup("xmlrpc:soap:helloWSDL.HelloService"); | | // get the hello stub | Hello hello = (Hello) svc.getHelloPort(); | | Stub stub = (Stub) hello; | | // set the end point address | stub._setProperty("javax.xml.rpc.service.endpoint.address", | args.length > 0 ? args[0] :"http://localhost:9090/helloWSDL"); | | | //set SSL props with byte[][] | setSSLProperties(stub); | | //invoke the service | System.out.println(hello.sayHello()); | | //set SSL props with X509 | setSSLProperties2(stub); | | //invoke the service | System.out.println(hello.sayHello()); | } private static void setSSLProperties(Stub stub) throws Exception { | //set certificate chain | File certFile = new File("clientCertChain.der"); | byte[][] certChain = loadChainFromFile(certFile); | stub._setProperty(SSLProperties.WSSDK_SSL_CERT_CHAIN, certChain); | | //set private key | File prkFile = new File("clientKey.pkcs8"); | byte[] prKey = loadFromFile(prkFile); | stub._setProperty(SSLProperties.WSSDK_SSL_PRIVATE_KEY, prKey); | | //set pass phrase | stub._setProperty(SSLProperties.WSSDK_SSL_PASS_PHRASE, "test"); | | //set root CAs | byte[][] rootCAs = getRootCAs(); | stub._setProperty(SSLProperties.WSSDK_SSL_ROOT_CA_CERTS, rootCAs); | } private static void setSSLProperties2(Stub stub) throws Exception { | //set certificate chain | byte[][] certChain = (byte[][]) | stub._getProperty(SSLProperties.WSSDK_SSL_CERT_CHAIN); | | X509Certificate[] certChainX509 = getX509s(certChain); | | stub._setProperty(SSLProperties.WSSDK_SSL_CERT_CHAIN, certChainX509); | | //set root CAs | byte[][] rootCAs = (byte[][]) | stub._getProperty(SSLProperties.WSSDK_SSL_ROOT_CA_CERTS); | | X509Certificate[] rootCAsX509 = getX509s(rootCAs); | | stub._setProperty(SSLProperties.WSSDK_SSL_ROOT_CA_CERTS, rootCAsX509); | } static byte[][] loadChainFromFile(File file) throws IOException { | DataInputStream dis = new DataInputStream(new FileInputStream(file)); | | // get the size of the chain | int chainLen = dis.readInt(); | byte[][] chain = new byte[chainLen][]; | | // read in the individual elements | for (int i=0; i < chainLen; i++) { | | chain[i] = new byte[dis.readInt()]; | | dis.readFully(chain[i]); | } | | // return the chain | dis.close(); return chain; } static byte[] loadFromFile(File file) throws IOException { | DataInputStream dis = new DataInputStream(new FileInputStream(file)); | byte[] bytes = new byte[dis.available()]; | dis.readFully(bytes); dis.close(); | return bytes; } static byte[][] getRootCAs() throws IOException { | ArrayList caList = new ArrayList(); | JarFile jarFile = new JarFile("../../lib/agrootca.jar"); | for (Enumeration e = jarFile.entries(); e.hasMoreElements() ;) { | | JarEntry ent = (JarEntry) e.nextElement(); | | if (!ent.getName().startsWith("META-INF/")) { | | | try { | | | | InputStream is = jarFile.getInputStream(ent); | | | | DataInputStream dis = new DataInputStream(is); | | | | byte[] bytes = new byte[dis.available()]; | | | | dis.readFully(bytes); dis.close(); | | | | caList.add(bytes); | | | } catch (Exception ex) { | | | | System.err.println("failed to load " + ent.getName() + | | | | " from " + jarFile + ": " + ex.getMessage()); | | | | if (System.getProperty("JBWDebug") != null) | | | | ex.printStackTrace(); | | | } | | } | } | byte[][] rootCAs = new byte[caList.size()][]; | caList.toArray(rootCAs); | return rootCAs; } static X509Certificate[] getX509s(byte[][] certs) throws Exception { | if (certs == null) return null; | X509Certificate[] x509s = new X509Certificate[certs.length]; | for (int i =0; i < certs.length; i++) | x509s[i] = getX509(certs[i]); | return x509s; } static X509Certificate getX509(byte[] certba) throws Exception { | CertificateFactory cf = CertificateFactory.getInstance("X.509"); | ByteArrayInputStream inStream = new ByteArrayInputStream(certba); | X509Certificate cert = | (X509Certificate)cf.generateCertificate(inStream); | inStream.close(); | return cert; } }2 Implementing the SSLCallClient
For the sake of completeness, a SSLCallClient is also provided to show how to use Call API to invoke a secure web service.package sslHello; import java.io.*; import java.security.cert.X509Certificate; import java.io.File; import javax.xml.rpc.ServiceFactory; import javax.xml.namespace.QName; import javax.xml.rpc.Service; import javax.xml.rpc.Call; import com.sssw.jbroker.web.security.SSLProperties; import helloWSDL.*; public class SSLCallClient extends SSLClient { public static void main(String[] args) throws Exception { | System.setProperty(ServiceFactory.SERVICEFACTORY_PROPERTY, | "com.sssw.jbroker.web.xml.rpc.ServiceFactoryDelegate"); | | ServiceFactory factory = ServiceFactory.newInstance(); | | QName qname = new QName("http://www.helloWSDL", "HelloService"); | | Service service = factory.createService(qname); | | QName portName = new QName("http://www.helloWSDL", "HelloPort"); | | String url = args.length > 0 ? args[0] : | "http://localhost:9090/helloWSDL"; | | sayHello(service, portName, url); } static void sayHello(Service service, QName portName, String url) throws Exception { | Call call = service.createCall(portName); | | QName r = new javax.xml.namespace.QName("", "arg0"); | | call.setReturnType(r, String.class); | | Object[] parms = {}; | | call.setTargetEndpointAddress(url); | | call.setProperty(Call.SOAPACTION_URI_PROPERTY, | "http://www.helloWSDL/sayHello"); | | call.setProperty(Call.OPERATION_STYLE_PROPERTY, "rpc"); | | call.setOperationName(new QName("http://www.helloWSDL", "sayHello")); | | String result = null; | | // before invoke, set SSL Properties | | setSSLProperties(call); | result = (String) call.invoke(parms); | System.out.println(result); | | setSSLProperties2(call); | result = (String) call.invoke(parms); | System.out.println(result); | } private static void setSSLProperties(Call call) throws Exception { | //set certificate chain | File certFile = new File("clientCertChain.der"); | byte[][] certChain = loadChainFromFile(certFile); | call.setProperty(SSLProperties.WSSDK_SSL_CERT_CHAIN, certChain); | | //set private key | File prkFile = new File("clientKey.pkcs8"); | byte[] prKey = loadFromFile(prkFile); | call.setProperty(SSLProperties.WSSDK_SSL_PRIVATE_KEY, prKey); | | //set pass phrase | call.setProperty(SSLProperties.WSSDK_SSL_PASS_PHRASE, "test"); | | //set root CAs | byte[][] rootCAs = getRootCAs(); | call.setProperty(SSLProperties.WSSDK_SSL_ROOT_CA_CERTS, rootCAs); | } private static void setSSLProperties2(Call call) throws Exception { | //set certificate chain | byte[][] certChain = (byte[][]) | call.getProperty(SSLProperties.WSSDK_SSL_CERT_CHAIN); | | X509Certificate[] certChainX509 = getX509s(certChain); | | call.setProperty(SSLProperties.WSSDK_SSL_CERT_CHAIN, certChainX509); | | //set root CAs | byte[][] rootCAs = (byte[][]) | call.getProperty(SSLProperties.WSSDK_SSL_ROOT_CA_CERTS); | | X509Certificate[] rootCAsX509 = getX509s(rootCAs); | | call.setProperty(SSLProperties.WSSDK_SSL_ROOT_CA_CERTS, rootCAsX509); | } }Please see README file to build and run the example.
Copyright © 2000-2003, Novell, Inc. All rights reserved.