我们常见的SSL验证较多的只是验证我们的服务器是否是真实正确的,当然如果你访问的URL压根就错了,那谁也没有办法。这个就是所谓的SSL单向认证。

但是实际中,我们有可能还会验证客户端是否符合要求,也就是给我们每个用户颁发一个证书,比且每个数字证书都是唯一的,不公开的。这样就能通过这个数字证书保证当前访问我服务器的这个用户是经过服务器认可的,其他人不可访问。

双向认证 从第一个层面上 确保了服务器 与客户端 都是互相认可的。那么他们之间要进行通信,就会在通信协议上附加SSL协议,确保通信的内容是加密的,即使是sniffer这样的网络嗅探工具看到的都是 乱码。以后给大家演示下不加密的情况下,用sniffer看到的是什么。恐怕这样你就能提高警惕了。

以下内容从网络上摘抄 加以实际验证后修改的。

模拟场景:
Server端和Client端通信,需要进行授权和身份的验证,即Client只能接受Server的消息,Server只能接受Client的消息。

实现技术:
JSSE(Java Security Socket Extension)
是Sun为了解决在Internet上的安全通讯而推出的解决方案。它实现了SSL和TSL(传输层安全)协议。在JSSE中包含了数据加密,服务器验
证,消息完整性和客户端验证等技术。通过使用JSSE,开发人员可以在客户机和服务器之间通过TCP/IP协议安全地传输数据。

为了实现消息认证。
Server需要:
1)KeyStore: 其中保存服务端的私钥
2)Trust KeyStore:其中保存客户端的授权证书
同样,Client需要:
1)KeyStore:其中保存客户端的私钥
2)Trust KeyStore:其中保存服务端的授权证书

在这里我还是推荐使用Java自带的keytool命令,去生成这样信息文件。当然目前非常流行的开源的生成SSL证书的还有OpenSSL。
OpenSSL用C语言编写,跨系统。但是我们可能在以后的过程中用java程序生成证书的方便性考虑,还是用JDK自带的keytool。

1)生成服务端私钥,并且导入到服务端KeyStore文件中
keytool -genkey -alias serverkey -keystore kserver.keystore
过程中,分别需要填写,根据需求自己设置就行
keystore密码:123456
名字和姓氏:jin
组织单位名称:none
组织名称:none
城市或区域名称:BJ
州或省份名称:BJ
国家代码:CN
serverkey私钥的密码,不填写和keystore的密码一致。这里千万注意,直接回车就行了,不用修改密码。否则在后面的程序中以及无法直接应用这个私钥,会报错。

就可以生成kserver.keystore文件
server.keystore是给服务端用的,其中保存着自己的私钥

2)根据私钥,导出服务端证书
keytool -export -alias serverkey -keystore kserver.keystore -file server.crt
server.crt就是服务端的证书

3)将服务端证书,导入到客户端的Trust KeyStore中
keytool -import -alias serverkey -file server.crt -keystore tclient.keystore
tclient.keystore是给客户端用的,其中保存着受信任的证书

采用同样的方法,生成客户端的私钥,客户端的证书,并且导入到服务端的Trust KeyStore中
1)keytool -genkey -alias clientkey -keystore kclient.keystore
2)keytool -export -alias clientkey -keystore kclient.keystore -file client.crt
3)keytool -import -alias clientkey -file client.crt -keystore tserver.keystore

如此一来,生成的文件分成两组
服务端保存:kserver.keystore tserver.keystore
客户端保存:kclient.keystore  tclient.kyestore

以下是通过Java Socket通信程序来验证我们生成的证书是否可用。

客户端:

客户端代码  
  1. package examples.ssl;
  2. import java.io.BufferedInputStream;
  3. import java.io.BufferedOutputStream;
  4. import java.io.FileInputStream;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.io.OutputStream;
  8. import java.security.KeyStore;
  9. import javax.net.ssl.KeyManagerFactory;
  10. import javax.net.ssl.SSLContext;
  11. import javax.net.ssl.SSLSocket;
  12. import javax.net.ssl.TrustManagerFactory;
  13. /**
  14. * SSL Client
  15. *
  16. */
  17. public class SSLClient {
  18. private static final String DEFAULT_HOST                    = "127.0.0.1";
  19. private static final int    DEFAULT_PORT                    = 7777;
  20. private static final String CLIENT_KEY_STORE_PASSWORD       = "123456";
  21. private static final String CLIENT_TRUST_KEY_STORE_PASSWORD = "123456";
  22. private SSLSocket           sslSocket;
  23. /**
  24. * 启动客户端程序
  25. *
  26. * @param args
  27. */
  28. public static void main(String[] args) {
  29. SSLClient client = new SSLClient();
  30. client.init();
  31. client.process();
  32. }
  33. /**
  34. * 通过ssl socket与服务端进行连接,并且发送一个消息
  35. */
  36. public void process() {
  37. if (sslSocket == null) {
  38. System.out.println("ERROR");
  39. return;
  40. }
  41. try {
  42. InputStream input = sslSocket.getInputStream();
  43. OutputStream output = sslSocket.getOutputStream();
  44. BufferedInputStream bis = new BufferedInputStream(input);
  45. BufferedOutputStream bos = new BufferedOutputStream(output);
  46. bos.write("Client Message".getBytes());
  47. bos.flush();
  48. byte[] buffer = new byte[20];
  49. bis.read(buffer);
  50. System.out.println(new String(buffer));
  51. sslSocket.close();
  52. } catch (IOException e) {
  53. System.out.println(e);
  54. }
  55. }
  56. /**
  57. * <ul>
  58. * <li>ssl连接的重点:</li>
  59. * <li>初始化SSLSocket</li>
  60. * <li>导入客户端私钥KeyStore,导入客户端受信任的KeyStore(服务端的证书)</li>
  61. * </ul>
  62. */
  63. public void init() {
  64. try {
  65. SSLContext ctx = SSLContext.getInstance("SSL");
  66. KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
  67. TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
  68. KeyStore ks = KeyStore.getInstance("JKS");
  69. KeyStore tks = KeyStore.getInstance("JKS");
  70. ks.load(new FileInputStream("E://kclient.keystore"), CLIENT_KEY_STORE_PASSWORD.toCharArray());
  71. tks.load(new FileInputStream("E://tclient.keystore"), CLIENT_TRUST_KEY_STORE_PASSWORD.toCharArray());
  72. kmf.init(ks, CLIENT_KEY_STORE_PASSWORD.toCharArray());
  73. tmf.init(tks);
  74. ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
  75. sslSocket = (SSLSocket) ctx.getSocketFactory().createSocket(DEFAULT_HOST, DEFAULT_PORT);
  76. } catch (Exception e) {
  77. System.out.println(e);
  78. }
  79. }
  80. }

服务器端:

Java代码  
  1. package examples.ssl;
  2. import java.io.BufferedInputStream;
  3. import java.io.BufferedOutputStream;
  4. import java.io.FileInputStream;
  5. import java.io.InputStream;
  6. import java.io.OutputStream;
  7. import java.net.Socket;
  8. import java.security.KeyStore;
  9. import javax.net.ssl.KeyManagerFactory;
  10. import javax.net.ssl.SSLContext;
  11. import javax.net.ssl.SSLServerSocket;
  12. import javax.net.ssl.TrustManagerFactory;
  13. /***********************************************************************************************************************
  14. * <ul>
  15. * <li>1)生成服务端私钥</li>
  16. * <li>keytool -genkey -alias serverkey -keystore kserver.keystore</li>
  17. * <li>2)根据私钥,到处服务端证书</li>
  18. * <li>keytool -exoport -alias serverkey -keystore kserver.keystore -file server.crt</li>
  19. * <li>3)把证书加入到客户端受信任的keystore中</li>
  20. * <li>keytool -import -alias serverkey -file server.crt -keystore tclient.keystore</li>
  21. * </ul>
  22. **********************************************************************************************************************/
  23. /**
  24. * SSL Server
  25. *
  26. */
  27. public class SSLServer {
  28. private static final int    DEFAULT_PORT                    = 7777;
  29. private static final String SERVER_KEY_STORE_PASSWORD       = "123456";
  30. private static final String SERVER_TRUST_KEY_STORE_PASSWORD = "123456";
  31. private SSLServerSocket     serverSocket;
  32. /**
  33. * 启动程序
  34. *
  35. * @param args
  36. */
  37. public static void main(String[] args) {
  38. SSLServer server = new SSLServer();
  39. server.init();
  40. server.start();
  41. }
  42. /**
  43. * <ul>
  44. * <li>听SSL Server Socket</li>
  45. * <li> 由于该程序不是演示Socket监听,所以简单采用单线程形式,并且仅仅接受客户端的消息,并且返回客户端指定消息</li>
  46. * </ul>
  47. */
  48. public void start() {
  49. if (serverSocket == null) {
  50. System.out.println("ERROR");
  51. return;
  52. }
  53. while (true) {
  54. try {
  55. Socket s = serverSocket.accept();
  56. InputStream input = s.getInputStream();
  57. OutputStream output = s.getOutputStream();
  58. BufferedInputStream bis = new BufferedInputStream(input);
  59. BufferedOutputStream bos = new BufferedOutputStream(output);
  60. byte[] buffer = new byte[20];
  61. bis.read(buffer);
  62. System.out.println(new String(buffer));
  63. bos.write("Server Echo".getBytes());
  64. bos.flush();
  65. s.close();
  66. } catch (Exception e) {
  67. System.out.println(e);
  68. }
  69. }
  70. }
  71. /**
  72. * <ul>
  73. * <li>ssl连接的重点:</li>
  74. * <li>初始化SSLServerSocket</li>
  75. * <li>导入服务端私钥KeyStore,导入服务端受信任的KeyStore(客户端的证书)</li>
  76. * </ul>
  77. */
  78. public void init() {
  79. try {
  80. SSLContext ctx = SSLContext.getInstance("SSL");
  81. KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
  82. TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
  83. KeyStore ks = KeyStore.getInstance("JKS");
  84. KeyStore tks = KeyStore.getInstance("JKS");
  85. ks.load(new FileInputStream("E://kserver.keystore"), SERVER_KEY_STORE_PASSWORD.toCharArray());
  86. tks.load(new FileInputStream("E://tserver.keystore"), SERVER_TRUST_KEY_STORE_PASSWORD.toCharArray());
  87. kmf.init(ks, SERVER_KEY_STORE_PASSWORD.toCharArray());
  88. tmf.init(tks);
  89. ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
  90. serverSocket = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(DEFAULT_PORT);
  91. serverSocket.setNeedClientAuth(true);
  92. } catch (Exception e) {
  93. e.printStackTrace();
  94. }
  95. }
  96. }

http://blog.csdn.net/binyao02123202/article/details/7702989

Java实现 SSL双向认证的更多相关文章

  1. SSL双向认证java实现(转)

    本文通过模拟场景,介绍SSL双向认证的java实现 默认的情况下,我认为读者已经对SSL原理有一定的了解,所以文章中对SSL的原理,不做详细的介绍. 如果有这个需要,那么通过GOOGLE,可以搜索到很 ...

  2. tomcat配置SSL双向认证

    一.SSL简单介绍 SSL(Secure Sockets Layer 安全套接层)就是一种协议(规范),用于保障客户端和服务器端通信的安全,以免通信时传输的信息被窃取或者修改. 怎样保障数据传输安全? ...

  3. SSL双向认证(高清版)

    介绍了SSL双向认证的一些基本问题,以及使用Nginx+PHP基于它搭建https的Webservice. 之前的方式只是实现1:1的模式,昨天同事继续实现了n:1的模式,这里我再整理记录下. 由于n ...

  4. php实现https(tls/ssl)双向认证

    php实现https(tls/ssl)双向认证 通常情况下,在部署https的时候,是基于ssl单向认证的,也就是说只要客户端认证服务器,而服务器不需要认证客户端. 但在一些安全性较高的场景,如银行, ...

  5. 在 kafka 的 broke 和 client 之间加入 SSL 双向认证

    在 kafka 的 broke 和 client 之间加入 SSL 双向认证https://blog.csdn.net/hohoo1990/article/details/79110031 kafka ...

  6. C++ windows客户端支持SSL双向认证

    C++ windows客户端支持SSL双向认证,服务端是JAVA开发的,使用的证书是jks格式的.C++并不支持JKS格式的证书,所以要用openssl进行转换下. 1. 需要先把jks转成.p12文 ...

  7. Nginx、SSL双向认证、PHP、SOAP、Webservice、https

    本文是1:1模式,N:1模式请参见新的一篇博客<SSL双向认证(高清版)> ----------------------------------------------------- 我是 ...

  8. JAVA中SSL证书认证通讯

    JAVA中SSL证书认证通讯 SSL通讯服务端 /******************************************************************** * 项目名称 ...

  9. apache用户认证,ssl双向认证配置

    安装环境: OS:contos 6.4 httpd:httpd-2.2.15-59.el6.centos.i686.rpm openssl:openssl-1.0.1e-57.el6.i686.rpm ...

随机推荐

  1. Asp.Net Core WebAPI入门整理(三)跨域处理

    一.Core  WebAPI中的跨域处理  1.在使用WebAPI项目的时候基本上都会用到跨域处理 2.Core WebAPI的项目中自带了跨域Cors的处理,不需要单独添加程序包 3.使用方法简单 ...

  2. Code alignment 代码对齐改进(VS2017)

    In mathematics you always keep your equals lined up directly underneath the one above. It keeps it c ...

  3. 如何重置mate的面板到初始化时的默认设置?

    在你的任何终端中敲入如下命令: gsettings reset-recursively org.mate.panel

  4. Spring AOP 入门实例详解

    目录 AOP概念 AOP核心概念 Spring对AOP的支持 基于Spring的AOP简单实现 基于Spring的AOP使用其他细节 AOP概念 AOP(Aspect Oriented Program ...

  5. A. 【UR #16】破坏发射台

    题解: 首先看n是偶数的 那么就是不需要满足对面这个性质的 这样就可以dp了 f[i][0/1]表示dp到第i位,当前数等于或不等于第一位的方案数 然后显然可以用矩阵优化 再考虑n为奇数 用一样的思路 ...

  6. EL 表达式截取字符串/替换字符/……

    <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> 下面是 ...

  7. k8s 关键字以及管理流程。

    一.流程图如下 二.用户通过kubectl提交需要运行的docker container(pod). 三.api server把请求存储在etcd里面. 四.scheduler(调度)扫描,分配机器. ...

  8. Arbitrage HDU1217

    汇率转换问题: 怎么样才能套利 可以用Floyd算法: #include<bits/stdc++.h> using namespace std; ][]; int main() { int ...

  9. 【Java】 剑指offer(61) 扑克牌的顺子

      本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连 ...

  10. 在Spring中配置SQL server 2000

    前言 Lz主要目的是在Spring中配置SQL server 2000数据库,但实现目的的过程中参差着许多SQL server 2000的知识,也包罗在本文记载下来!(Lz为什么要去搞sql serv ...