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. 输入<sslsockettwo>的主密码  
  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. 保存在文件中的认证 <e:\keytool\sslsockettwo.cer>  

        (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 是否将在开始时配置为请求 客户端验证。 
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SSL双向认证是指在SSL连接中,不仅客户端要验证服务器的身份,服务器也要验证客户端的身份。Java实现SSL双向认证一般需要以下步骤: 1. 创建KeyStore和TrustStore,分别存储客户端和服务器的证书和私钥。可以使用keytool工具来创建这些文件。 2. 在服务器端,创建SSLContext对象,并为其指定KeyManagerFactory和TrustManagerFactory。这些工厂类可以使用KeyStore和TrustStore来初始化。 3. 在客户端,创建SSLContext对象,并为其指定TrustManagerFactory。这个工厂类可以使用TrustStore来初始化。 4. 在服务器端,创建ServerSocket并开始监听客户端连接。当客户端连接到服务器时,服务器会为客户端创建一个SSLSocket并开始SSL握手。 5. 在客户端,创建SSLSocket并连接到服务器。客户端和服务器会进行SSL握手,包括交换证书和验证身份等步骤。 6. 客户端和服务器建立SSL连接后,可以开始进行安全通信。 下面是一个简单的Java SSL双向认证的示例代码: 服务器端: ```java KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(new FileInputStream("server.jks"), "password".toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(keyStore, "password".toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(keyStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory(); SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(8443); while (true) { SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); // 处理客户端连接 } ``` 客户端: ```java KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(new FileInputStream("client.jks"), "password".toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(keyStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), null); SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket("localhost", 8443); // 发送和接收数据 ``` 需要注意的是,这只是一个简单的示例代码,实际中还需要考虑证书的管理、密码的安全等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值