SSL(TLS) Authentication:Web Services and Java
2013-04-23 16:21
351 查看
In this article we will talk about the SSL(TLS) authentication implementation as required when say calling a web serivce or making an HTTP get call using Java. SSL authentication can be either one way or mutual - where both consumer and provider must authenticate
themselves. Lets first start with consumer of a web service. For a web service consumer, there are two major entities that you will be working with The Service endpoint interface(port) and the Service class itself. Lets look at how you obtain the port
This method will return you the port of the service you are trying to consume when the address is provided
JaxWsProxyFactoryBean beanFactory = new JaxWsProxyFactoryBean();
beanFactory.setServiceClass(KtipServiceSoap.class);
beanFactory.setAddress("http://localhost:port/KtipService/xxxx");
return (KtipServiceSoap)beanFactory.create();
[align=center]Listing I
[/align]
The SSL authenticaion parameters are passed in through the org.apache.cxf.transport.http.HTTPConduit. (Please note instead of passing SSL parameters through the configuration file, we are passing in through the code ). To get the conduit we must first
get the org.apache.cxf.endpoint.Client fromthe port we just obtained. This is done as shown in Listing II.
KtipServiceSoap port = ...// obtained using the code from Listing I
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(port);
HTTPConduit conduit = (HTTPConduit)client.getConduit();
conduit.setTlsClientParameters(fillTLSParameters());
[align=center]Listing II
[/align]
Now we will look at how we actually set the TLS parameters for the conduit. We can call a method that will populate the required parameters. The method will look as shown below in Listing III.
org.apache.cxf.configuration.jsse.TLSClientParameters tlsParams = new TLSClientParameters();
tlsParams.setSecureSocketProtocol("SSL");
tlsParams.setDisableCNCheck(true);
KeyStore keyStore;
// Add trust managers (to authenticate the service)
keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream(new File("jks file location")), new String("password").toCharArray());
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(keyStore);
TrustManager[] trustMgr = trustFactory.getTrustManagers();
tlsParams.setTrustManagers(trustMgr);
// Add key managers (to authenticate the client)
keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(new File("pfx file location")), new String("password").toCharArray());
KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, new String("customerInfoSys").toCharArray());
KeyManager[] keyMgr = keyFactory.getKeyManagers();
tlsParams.setKeyManagers(keyMgr);
FiltersType filter = new FiltersType();
filter.getInclude().add(".*_EXPORT_.*");
filter.getInclude().add(".*_EXPORT1024_.*");
filter.getInclude().add(".*_WITH_DES_.*");
filter.getInclude().add(".*_WITH_NULL_.*");
filter.getExclude().add(".*_DH_anon_.*");
tlsParams.setCipherSuitesFilter(filter);
return tlsParams;
[align=center]Listing III
[/align]
So when you build your consumer, you should be provided .jks and .pfx files (and passwords for each) for mutual authentication. If there is only one way authentication to be performed by the service only and not the client, this would be done as shown in Listing
IV.
org.apache.cxf.configuration.jsse.TLSClientParameters tlsParams = new TLSClientParameters();
tlsParams.setSecureSocketProtocol("SSL");
tlsParams.setDisableCNCheck(true);
KeyStore keyStore;
// Add trust managers (to authenticate the client)
keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(new File("pfx file location")), new String("password").toCharArray());
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(keyStore);
TrustManager[] trustMgr = trustFactory.getTrustManagers();
tlsParams.setTrustManagers(trustMgr);
FiltersType filter = new FiltersType();
filter.getInclude().add(".*_EXPORT_.*");
filter.getInclude().add(".*_EXPORT1024_.*");
filter.getInclude().add(".*_WITH_DES_.*");
filter.getInclude().add(".*_WITH_NULL_.*");
filter.getExclude().add(".*_DH_anon_.*");
tlsParams.setCipherSuitesFilter(filter);
return tlsParams;
[align=center]Listing IV
[/align]
In this part I will show how to write a simple Java method to make a HTTP GET/POST when the caller has to be authenticated
String getHTMLData(String address) throws Exception{
String response = null;
URLConnection connection = new URL(address).openConnection();
HttpsURLConnection sslConnection = null;
HttpURLConnection nonsslConnection = null;
if(connection instanceof HttpsURLConnection){
sslConnection = (HttpsURLConnection)connection;
sslConnection.setSSLSocketFactory(createSocketFactory());
sslConnection.setRequestMethod("GET");
if(sslConnection.getResponseCode() == HttpsURLConnection.HTTP_INTERNAL_ERROR ){
throw new AdServerException("Problem calling ad server...");
}
}else if(connection instanceof HttpURLConnection){
nonsslConnection = (HttpURLConnection)connection;
nonsslConnection.setRequestMethod("GET");
}
BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder data = new StringBuilder(150);
String line;
while ((line = rd.readLine()) != null) data.append(line);
rd.close();
response = data.toString();
if(connection instanceof HttpsURLConnection) sslConnection.disconnect();
else if(connection instanceof HttpURLConnection) nonsslConnection.disconnect();
return response;
}
[align=center]Listing V
[/align]
To create the HTTPS connection with the right SSL parameters, you use the javax.net.ssl.SSLSocketFactory. As shown in listing VI
SSLSocketFactory createSocketFactory() throws Exception {
KeyStore keyStore;
// This is a one-way authentication
keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(new File("pfx file location")),
new String("pfx password").toCharArray());
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(keyStore);
TrustManager[] tm = trustFactory.getTrustManagers();
SSLContext context = SSLContext.getInstance("SSLv3");
context.init(null, tm, null);
SSLSocketFactory socketFactory = context.getSocketFactory();
return socketFactory;
}
[align=center]Listing VI
[/align]
themselves. Lets first start with consumer of a web service. For a web service consumer, there are two major entities that you will be working with The Service endpoint interface(port) and the Service class itself. Lets look at how you obtain the port
This method will return you the port of the service you are trying to consume when the address is provided
JaxWsProxyFactoryBean beanFactory = new JaxWsProxyFactoryBean();
beanFactory.setServiceClass(KtipServiceSoap.class);
beanFactory.setAddress("http://localhost:port/KtipService/xxxx");
return (KtipServiceSoap)beanFactory.create();
[align=center]Listing I
[/align]
The SSL authenticaion parameters are passed in through the org.apache.cxf.transport.http.HTTPConduit. (Please note instead of passing SSL parameters through the configuration file, we are passing in through the code ). To get the conduit we must first
get the org.apache.cxf.endpoint.Client fromthe port we just obtained. This is done as shown in Listing II.
KtipServiceSoap port = ...// obtained using the code from Listing I
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(port);
HTTPConduit conduit = (HTTPConduit)client.getConduit();
conduit.setTlsClientParameters(fillTLSParameters());
[align=center]Listing II
[/align]
Now we will look at how we actually set the TLS parameters for the conduit. We can call a method that will populate the required parameters. The method will look as shown below in Listing III.
org.apache.cxf.configuration.jsse.TLSClientParameters tlsParams = new TLSClientParameters();
tlsParams.setSecureSocketProtocol("SSL");
tlsParams.setDisableCNCheck(true);
KeyStore keyStore;
// Add trust managers (to authenticate the service)
keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream(new File("jks file location")), new String("password").toCharArray());
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(keyStore);
TrustManager[] trustMgr = trustFactory.getTrustManagers();
tlsParams.setTrustManagers(trustMgr);
// Add key managers (to authenticate the client)
keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(new File("pfx file location")), new String("password").toCharArray());
KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, new String("customerInfoSys").toCharArray());
KeyManager[] keyMgr = keyFactory.getKeyManagers();
tlsParams.setKeyManagers(keyMgr);
FiltersType filter = new FiltersType();
filter.getInclude().add(".*_EXPORT_.*");
filter.getInclude().add(".*_EXPORT1024_.*");
filter.getInclude().add(".*_WITH_DES_.*");
filter.getInclude().add(".*_WITH_NULL_.*");
filter.getExclude().add(".*_DH_anon_.*");
tlsParams.setCipherSuitesFilter(filter);
return tlsParams;
[align=center]Listing III
[/align]
So when you build your consumer, you should be provided .jks and .pfx files (and passwords for each) for mutual authentication. If there is only one way authentication to be performed by the service only and not the client, this would be done as shown in Listing
IV.
org.apache.cxf.configuration.jsse.TLSClientParameters tlsParams = new TLSClientParameters();
tlsParams.setSecureSocketProtocol("SSL");
tlsParams.setDisableCNCheck(true);
KeyStore keyStore;
// Add trust managers (to authenticate the client)
keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(new File("pfx file location")), new String("password").toCharArray());
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(keyStore);
TrustManager[] trustMgr = trustFactory.getTrustManagers();
tlsParams.setTrustManagers(trustMgr);
FiltersType filter = new FiltersType();
filter.getInclude().add(".*_EXPORT_.*");
filter.getInclude().add(".*_EXPORT1024_.*");
filter.getInclude().add(".*_WITH_DES_.*");
filter.getInclude().add(".*_WITH_NULL_.*");
filter.getExclude().add(".*_DH_anon_.*");
tlsParams.setCipherSuitesFilter(filter);
return tlsParams;
[align=center]Listing IV
[/align]
In this part I will show how to write a simple Java method to make a HTTP GET/POST when the caller has to be authenticated
String getHTMLData(String address) throws Exception{
String response = null;
URLConnection connection = new URL(address).openConnection();
HttpsURLConnection sslConnection = null;
HttpURLConnection nonsslConnection = null;
if(connection instanceof HttpsURLConnection){
sslConnection = (HttpsURLConnection)connection;
sslConnection.setSSLSocketFactory(createSocketFactory());
sslConnection.setRequestMethod("GET");
if(sslConnection.getResponseCode() == HttpsURLConnection.HTTP_INTERNAL_ERROR ){
throw new AdServerException("Problem calling ad server...");
}
}else if(connection instanceof HttpURLConnection){
nonsslConnection = (HttpURLConnection)connection;
nonsslConnection.setRequestMethod("GET");
}
BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder data = new StringBuilder(150);
String line;
while ((line = rd.readLine()) != null) data.append(line);
rd.close();
response = data.toString();
if(connection instanceof HttpsURLConnection) sslConnection.disconnect();
else if(connection instanceof HttpURLConnection) nonsslConnection.disconnect();
return response;
}
[align=center]Listing V
[/align]
To create the HTTPS connection with the right SSL parameters, you use the javax.net.ssl.SSLSocketFactory. As shown in listing VI
SSLSocketFactory createSocketFactory() throws Exception {
KeyStore keyStore;
// This is a one-way authentication
keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(new File("pfx file location")),
new String("pfx password").toCharArray());
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(keyStore);
TrustManager[] tm = trustFactory.getTrustManagers();
SSLContext context = SSLContext.getInstance("SSLv3");
context.init(null, tm, null);
SSLSocketFactory socketFactory = context.getSocketFactory();
return socketFactory;
}
[align=center]Listing VI
[/align]
相关文章推荐
- 读《Java Web Services: Up and Running》
- Consuming P6 Web Services over HTTPS (SSL) From Java
- 配置JAVA SSL/TLS 之websocket wss交互式认证
- Web Services between .NET, Java and MS SOAP Toolkit
- Java Web services and Apache Tomcat
- Combine Web and Windows Services to Run Your ASP.NET Code at Scheduled
- Tomcat version 7.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 and 6 Web
- Java SSL/TLS 安全通讯协议(SSLSocket)
- 为没有web选项的eclipse添加web and JavaEE插件
- Spring之集成之Remoting and web services using Spring
- jboss7 Java API for RESTful Web Services (JAX-RS) 官方文档
- HTTPS协议--HTTPS权威指南:在服务器和Web应用上部署SSL/TLS和PKI (/book/1734)
- Create intelligent Web spiders -How to use Java network objects and HTML objects
- Java Restful Web Services (一)
- Java SSL/TLS 安全通讯协议介绍
- RESTful Webservices with Java (Jersey / JAX-RS)
- Interactive and verifiable web services composition, specification reformulation and substitution
- java端RESTful web services的几种实现方式
- Eclipse报错:Tomcat version 7.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 and 6 Web modules
- 为经典版eclipse添加web and JavaEE插件