JAVA SSL SOCKET通信服务器端客户端证书双向认证

浅谈基于SSL的Socket通信  
        在 上一篇 中提到的是客户端对于服务器的验证,即服务器是否可信。若希望配置双向认证的话,即当客户端信任服务器,向服务器发送数据,同样服务器也要判断客户端是否可信,则客户端也需要将其数字证书导入到服务器的密钥库中。 
        在 上一篇 中我们已经创建了服务器端的密钥库,并从其中导出了数字证书,客户端将服务器的数字证书导入到了自己的密钥库中,连接服务器的时候用来验证服务器的身份。 
        在这里我们只需要创建客户端的密钥库,并从中导出数字证书,并将该证书导入到服务器端的密钥库中,当客户端连接服务器时验证客户端的身份。 
        基于 上一篇 执行如下三个步骤的操作: 
       (a) 生成客户端密钥库 
Java代码   收藏代码
  1. keytool.exe -genkeypair -v -alias sslsockettwo -keyalg RSA -keystore e:\keytool\sslclienttwo.keystore  

生成客户端密钥库提示代码   收藏代码
  1. 输入keystore密码:  
  2. 再次输入新密码:  
  3. 您的名字与姓氏是什么?  
  4.   [Unknown]:  cr  
  5. 您的组织单位名称是什么?  
  6.   [Unknown]:  han  
  7. 您的组织名称是什么?  
  8.   [Unknown]:  s  
  9. 您所在的城市或区域名称是什么?  
  10.   [Unknown]:  bj  
  11. 您所在的州或省份名称是什么?  
  12.   [Unknown]:  bj  
  13. 该单位的两字母国家代码是什么  
  14.   [Unknown]:  zh  
  15. CN=cr, OU=han, O=s, L=bj, ST=bj, C=zh 正确吗?  
  16.   [否]:  y  

生成客户端密钥库结果代码   收藏代码
  1. 正在为以下对象生成 1,024 位 RSA 密钥对和自签名证书 (SHA1withRSA)(有效期为 90 天):  
  2.          CN=cr, OU=han, O=s, L=bj, ST=bj, C=zh  
  3. 输入的主密码  
  4.         (如果和 keystore 密码相同,按回车):  
  5. [正在存储 e:\keytool\sslclienttwo.keystore]  

        (b) 从客户端密钥库导出数字证书 
Java代码   收藏代码
  1. keytool.exe -exportcert -v -alias sslsockettwo -file e:\keytool\sslsockettwo.cer -keystore e:\keytool\sslclienttwo.keystore  

导出客户端密钥库结果代码   收藏代码
  1. 输入keystore密码:  
  2. 保存在文件中的认证   

        (c) 将客户端数字证书导入到服务器的密钥库中 
Java代码   收藏代码
  1. keytool.exe -importcert -v -alias sslsockettwocer -file e:\keytool\sslsockettwo.cer -keystore e:\keytool\sslsocketserver.keystore  

导入提示代码   收藏代码
  1. 输入keystore密码:  
  2. 再次输入新密码:  
  3. 所有者:CN=cr, OU=han, O=s, L=bj, ST=bj, C=zh  
  4. 签发人:CN=cr, OU=han, O=s, L=bj, ST=bj, C=zh  
  5. 序列号:4ce61d58  
  6. 有效期: Fri Nov 19 14:46:48 CST 2010 至Thu Feb 17 14:46:48 CST 2011  
  7. 证书指纹:  
  8.          MD5:54:84:28:A5:C8:E5:4D:18:7E:A7:56:6B:16:3E:10:62  
  9.          SHA1:1D:36:F0:6E:CC:FF:86:15:D4:9F:28:B6:85:95:BA:79:23:29:A6:CF  
  10.          签名算法名称:SHA1withRSA  
  11.          版本: 3  
  12. 信任这个认证? [否]:  y  
  13. 认证已添加至keystore中  
  14. [正在存储 e:\keytool\sslsocketserver.keystore]  

         (d) 创建服务器端Socket对象 
Java代码   收藏代码
  1. public class TestSSLSocketServer {  
  2.     private static String kpath = "e:\\keytool\\sslsocket.keystore";  
  3.     private static String tpath = "e:\\keytool\\sslsocketserver.keystore";  
  4.     private static char[] password = "aaaaaaa".toCharArray();  
  5.     public static void main(String[] args) {  
  6.         boolean flag = true;  
  7.         SSLContext context = null;  
  8.         try {  
  9.             KeyStore ks = KeyStore.getInstance("JKS");  
  10.             ks.load(new FileInputStream(kpath), password);  
  11.             KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");  
  12.             kmf.init(ks, password);  
  13.             KeyManager[] km = kmf.getKeyManagers();  
  14.             KeyStore ts = KeyStore.getInstance("JKS");  
  15.             ts.load(new FileInputStream(tpath), password);  
  16.             TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");  
  17.             tmf.init(ts);  
  18.             TrustManager[] tm = tmf.getTrustManagers();  
  19.             context = SSLContext.getInstance("SSL");  
  20.             context.init(km, tm, null);  
  21.         } catch (..... e) {  
  22.             e.printStackTrace();   //捕获异常  
  23.         }  
  24.         SSLServerSocketFactory ssf = (SSLServerSocketFactory) context.getServerSocketFactory();  
  25.         try {  
  26.             SSLServerSocket ss = (SSLServerSocket) ssf.createServerSocket(8000);  
  27.             /** 
  28.              * 此处不是太明白:三个方法具体什么作用 
  29.              */  
  30.             //ss.setNeedClientAuth(true);  
  31.             //ss.setUseClientMode(true);  
  32.             //ss.setWantClientAuth(true);  
  33.             System.out.println("等待客户点连接。。。");  
  34.             while (flag) {  
  35.                 Socket s = ss.accept();  
  36.                 System.out.println("接收到客户端连接");  
  37.                 ObjectOutputStream os = new ObjectOutputStream(s.getOutputStream());  
  38.                 os.writeObject("echo : Hello");  
  39.                 os.flush();  
  40.                 os.close();  
  41.                 System.out.println();  
  42.                 s.close();  
  43.             }  
  44.             ss.close();  
  45.         } catch (IOException e) {  
  46.             e.printStackTrace();  
  47.         }  
  48.     }  
  49. }  

         (e) 创建客户端Socket对象 
Java代码   收藏代码
  1. public class TestSSLSocketClient {  
  2.     private static String kpath = "e:\\keytool\\sslclienttwo.keystore";  
  3.     private static String tpath = "e:\\keytool\\sslclient.keystore";  
  4.     //private static String path = "e:\\keytool\\tclient.keystore";  
  5.     private static char[] password = "aaaaaaa".toCharArray();  
  6.   
  7.     /** 
  8.      * @param args 
  9.      */  
  10.     public static void main(String[] args) {  
  11.         SSLContext context = null;  
  12.         try {  
  13.             KeyStore ks = KeyStore.getInstance("JKS");  
  14.             ks.load(new FileInputStream(kpath), password);  
  15.             KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");  
  16.             kmf.init(ks, password);  
  17.             KeyManager [] km = kmf.getKeyManagers();  
  18.             KeyStore ts = KeyStore.getInstance("JKS");  
  19.             ts.load(new FileInputStream(tpath), password);  
  20.             TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");  
  21.             tmf.init(ts);  
  22.             TrustManager [] tm = tmf.getTrustManagers();  
  23.             context = SSLContext.getInstance("SSL");  
  24.             context.init(km, tm, null);  
  25.         } catch (...... e) {  
  26.             e.printStackTrace();  //捕获异常  
  27.         }   
  28.         SSLSocketFactory ssf = context.getSocketFactory();  
  29.         try {  
  30.             SSLSocket ss = (SSLSocket) ssf.createSocket("localhost"8000);  
  31.             /** 
  32.              * 此处不是太明白:三个方法具体什么作用 
  33.              */  
  34.             //ss.setNeedClientAuth(true);  
  35.             //ss.setUseClientMode(true);  
  36.             //ss.setWantClientAuth(true);  
  37.             System.out.println("客户端就绪。");  
  38.             ObjectInputStream br = new ObjectInputStream(ss.getInputStream());  
  39.             try {  
  40.                 System.out.println(br.readObject());  
  41.             } catch (ClassNotFoundException e) {  
  42.                 e.printStackTrace();  
  43.             }  
  44.             br.close();  
  45.             ss.close();  
  46.             System.out.println("客户端测试ok");  
  47.         } catch (UnknownHostException e) {  
  48.             e.printStackTrace();  
  49.         } catch (IOException e) {  
  50.             e.printStackTrace();  
  51.         }  
  52.     }  
  53. }  

        //以下为上述三个方法,来自JDK1.6 
Java代码   收藏代码
  1. abstract  void  setNeedClientAuth(boolean need)  
  2.     控制接受的服务器模式SSLSocket是否将在开始时配置为要求客户端验证。  
  3. abstract  void  setUseClientMode(boolean mode)  
  4.     控制接受的连接是以(默认的)SSL 服务器模式还是在 SSL 客户端模式工作。  
  5. abstract  void  setWantClientAuth(boolean want)  
  6.     控制 accept 服务器模式的 SSLSockets 是否将在开始时配置为请求 客户端验证。 

你可能感兴趣的:(JAVA SSL SOCKET通信服务器端客户端证书双向认证)