SSL双向认证Java实现 Tomcat篇

双向验证,在客户机连接服务器时,客户机验证服务器的证书,服务器验证客户机的证书,链接双方都要对彼此的数字证书进行验证,保证这是经过授权的才能够连接。

  1. 生成服务器端的keystore和truststore文件:

    1.1. 以jks格式生成服务器端包含Public key和Private Key的keystore文件,keypass与storepass务必要一样,因为在tomcat server.xml中只配置一个password.
    keytool -genkey -alias server -keystore serverKeystore.jks -keypass 123456 -storepass 123456 -keyalg RSA -keysize 512 -validity 365 -v -dname “CN = W03GCA01A,O = ABC BANK,DC = Server Https,DC = ABC,OU = Firefly Technology And Operation”

    1.2. 从keystore中导出别名为server的服务端证书.
    keytool -export -alias server -keystore serverKeystore.jks -storepass 123456 -file server.cer

    1.3. 将server.cer导入客户端的信任证书库clientTruststore.jks。
    keytool -import -alias trustServer -file server.cer -keystore clientTruststore.jks -storepass 123456

  2. 生成客户端的keystore和truststore文件:

    1.1. 以jks格式生成服务器端包含Public key和Private Key的keystore文件。
    keytool -genkey -alias client -keystore clientKeystore.jks -keypass 123456 -storepass 123456 -keyalg RSA -keysize 512 -validity 365 -v -dname “CN = W03GCA01A,O = ABC BANK,DC = Client Https,DC = ABC,OU = Firefly Technology And Operation”

    1.2. 从keystore中导出别名为client的客户端证书.
    keytool -export -alias client -keystore clientKeystore.jks -storepass 123456 -file client.cer

    1.3. 将client.cer导入服务端的信任证书库serverTruststore.jks。
    keytool -import -alias trustClient -file client.cer -keystore serverTruststore.jks -storepass 123456

    服务器端: serverKeystore.jks serverTruststore.jks
    客户端: clientKeystore.jks clientTruststore.jks


3.在tomcat 配置server.xml

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"  
               maxThreads="150" scheme="https" secure="true"  
           clientAuth="true" sslProtocol="TLS"   
           keystoreFile="keystore/serverKeystore.jks" keystorePass="123456"   
        truststoreFile="keystore/serverTruststore.jks" truststorePass="123456" /> 

4.客户端代码

    package com.ssl.http;  

    import java.io.File;  
    import java.io.FileInputStream;  
    import java.security.KeyStore;  
    import java.security.KeyStoreException;  

    import org.apache.http.HttpEntity;  
    import org.apache.http.HttpResponse;  
    import org.apache.http.client.methods.HttpGet;  
    import org.apache.http.conn.scheme.Scheme;  
    import org.apache.http.conn.ssl.SSLSocketFactory;  
    import org.apache.http.impl.client.DefaultHttpClient;  

    /** 
     *  
     * @author kevin 
     *  
     */  
    public class ClientTwoWaySSL {  

        /** 
         * @param args 
         * @throws Exception 
         */  
        public static void main(String[] args) throws Exception {  
            // TODO Auto-generated method stub  

            DefaultHttpClient httpclient = new DefaultHttpClient();  

            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());  
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());  

            FileInputStream keyStoreIn = new FileInputStream(new File(  
                    "com/ssl/http/clientKeystore.jks"));  
            FileInputStream trustStoreIn = new FileInputStream(new File(  
                    "com/ssl/http/clientTruststore.jks"));  

            try {  
                keyStore.load(keyStoreIn, "123456".toCharArray());  
                trustStore.load(trustStoreIn, "123456".toCharArray());  
            } finally {  
                keyStoreIn.close();  
                trustStoreIn.close();  
            }  

            SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore,  
                    "123456", trustStore);  
            Scheme sch = new Scheme("https", socketFactory, 8443);  

            httpclient.getConnectionManager().getSchemeRegistry().register(sch);  

            HttpGet httpget = new HttpGet("https://w03gca01a:8443/");  

            System.out.println("Request:" + httpget.getRequestLine());  

            HttpResponse response = httpclient.execute(httpget);  
            HttpEntity entity = response.getEntity();  

            System.out.println("----------------------------------------");  
            System.out.println(response.getStatusLine());  
            if (entity != null) {  
                System.out.println("Response content length: "  
                        + entity.getContentLength());  
            }  
            if (entity != null) {  
                entity.consumeContent();  
            }  
            httpclient.getConnectionManager().shutdown();  

        }  

    }  

备注:

A. 如出现如下error,请配置C:\WINDOWS\system32\drivers\etc\hosts, 将“127.0.0.1 w03gca01a” 加在hosts文件中

    # executing requestGET https://w03gca01a/ HTTP/1.1    
    # Exception in thread "main" javax.net.ssl.SSLException: hostname in certificate didn't match: <w03gca01a> != <localhost>    
    #     at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:220)

    #     at org.apache.http.conn.ssl.BrowserCompatHostnameVerifier.verify(BrowserCompatHostnameVerifier.java:54)

B. 本文用到 httpcore-4.0.1.jar httpclient-4.0.1.jar httpmime-4.0.1.jar,下载地址: http://hc.apache.org/downloads.cgi

C.报错:javax.net.ssl.SSLException: hostname in certificate didn’t match
解决方案: socketFactory.setHostnameVerifier(SSLSocketFactory. ALLOW_ ALL_HOSTNAME_VERIFIER);

本文转自:http://firefly.iteye.com/blog/667219

展开阅读全文

没有更多推荐了,返回首页