一、SSL简单介绍

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

  1. 怎样保障数据传输安全?

     客户端和服务器端在进行握手(客户端和服务器建立连接和交换参数的过程称之为握手)时会产生一个“对话密钥”(session key),用来加密接下来的数据传输,解密时也是用的这个“对话密钥”,而这个“对话密钥”只有客户端和服务器端知道。也就是说只要这个“对话密钥”不被破解,就能保证安全。

  2. 客户端证书和服务器端证书

    客户端证书和服务器端证书用于证明自己的身份,就好比每个人都有一张身份证,这种身份证是唯一的。一般来说,只要有服务器端的证书就可以了,但是有时需要客户端提供自己的证书,已证明其身份。

二、生成自签名的服务器端证书和导入服务器端信任证书库

    一般证书可以使用权威机构颁发的证书,如:veri sign,百度使用的就是veri sign颁发的证书,这样的权威证书机构是受信任的,但是这些机构颁发的证书往往是需要收费的,这样的证书也难得到。对于小型企业来说为了节约成本,常常使用自签名的证书。

    接下来使用JDK keytool工具来签发证书,如果未安装JDK,请先安装JDK(本文使用的是JDK7)。本文所有的证书文件都放到F:\ca,您可以选择一个目录来存放。

  1. 生成服务器端证书

keytool -genkeypair -v -alias server -keyalg RSA -validity 3650 -keystore ./server.keystore  -storepass 123456 -keypass 123456 -dname "CN=127.0.0.1,OU=rm,O=rm,L=gz,ST=gd,C=cn"

注意:-dname参数中的CN应该为服务器所在的ip或者域名

   

  2. 导出服务器端证书

    keytool -exportcert -alias server  -keystore ./server.keystore  -file ./server.cer  -storepass 123456

    

  3. 将服务器端证书导入信任证书

    keytool -importcert -alias serverca  -keystore ./server_trust.keystore  -file ./server.cer  -storepass 123456

    

三、生成客户端证书并导入到服务器端信任证书库

  1. 生成客户端证书

     keytool -genkeypair -v -alias client -dname "CN=rorymo" -keyalg RSA -validity 3650 -keypass 123456 -keystore ./client.p12 -storepass 123456 -storetype PKCS12

    

  2. 导出客户端证书

    keytool -exportcert -alias client -file ./client.cer -keystore ./client.p12 -storepass 123456 -storetype PKCS12

   

  3. 导入客户端证书到服务器端信任证书库

    keytool -importcert -alias clientca  -keystore ./server_trust.keystore  -file ./client.cer  -storepass 123456

   

  4. 查看服务器端信任证书库的信任证书信息

    keytool -list -keystore ./server_trust.keystore -storepass 123456

    

   可以看到信任证书库中已经导入了一张服务器端证书和一张客户端证书

  5. 至此我们已经生成了如下的文件

  

四、配置tomcat和web应用

  1. 将证书文件放到tomcat根目录下

将上图的server.keystore和server_trust.keystore放到tomcat的根目录下,例如我的tomcat目录为:F:\ca\apache-tomcat-7.0.64

   

  2. 配置tomcat

   编辑conf/server.xml文件加入如下的配置:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="${catalina.base}/server.keystore" keystorePass="123456"
truststoreFile ="${catalina.base}/server_trust.keystore" truststorePass="123456"/>

说明:

  • clientAuth为true表示开启SSL双向认证
  • keystoreFile指定服务器端的证书位置
  • truststoreFile指定服务器端信任证书库

  3. 编写用来获取客户端证书的servlet

 package com.rorymo.demo.ssl;

 import java.io.IOException;
import java.io.PrintWriter;
import java.security.cert.X509Certificate; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
*
* SSLServlet
*
* @author rorymo
* @version 1.0
*/
@WebServlet("/SSLServlet")
public class SSLServlet extends HttpServlet { private static final long serialVersionUID = 1601507150278487538L;
private static final String REQUEST_ATTR_CERT = "javax.servlet.request.X509Certificate";
private static final String CONTENT_TYPE = "text/plain;charset=UTF-8";
private static final String DEFAULT_ENCODING = "UTF-8";
private static final String SCHEME_HTTPS = "https"; public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType(CONTENT_TYPE);
response.setCharacterEncoding(DEFAULT_ENCODING);
PrintWriter out = response.getWriter();
X509Certificate[] certs = (X509Certificate[]) request.getAttribute(REQUEST_ATTR_CERT);
if (certs != null) {
int count = certs.length;
out.println("共检测到[" + count + "]个客户端证书");
for (int i = 0; i < count; i++) {
X509Certificate cert = certs[i];
out.println("客户端证书 [" + cert.getSubjectDN() + "]: ");
out.println("证书是否有效:" + (verifyCertificate(cert) ? "是" : "否"));
out.println("证书详细信息:\r" + cert.toString());
}
} else {
if (SCHEME_HTTPS.equalsIgnoreCase(request.getScheme())) {
out.println("这是一个HTTPS请求,但是没有可用的客户端证书");
} else {
out.println("这不是一个HTTPS请求,因此无法获得客户端证书列表 ");
}
}
out.close();
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
} /**
*
* 校验证书是否过期
*
*
* @param certificate
* @return
*/
private boolean verifyCertificate(X509Certificate certificate) {
boolean valid = true;
try {
certificate.checkValidity();
} catch (Exception e) {
e.printStackTrace();
valid = false;
}
return valid;
} }

  4. 在web应用的web.xml中加入如下配置

  <security-constraint>

    <web-resource-collection>

      <web-resource-name>SSL</web-resource-name>

      <url-pattern>/SSLServlet</url-pattern>

    </web-resource-collection>

    <user-data-constraint>

      <description>SSL required</description>

      <transport-guarantee>CONFIDENTIAL</transport-guarantee>

    </user-data-constraint>

  </security-constraint>

  说明:

  • 如果不加入这个配置,那么所有访问的地址都必须要使用SSL才能访问,有时我们可能只需要通过某个或者某些SSL地址获取客户端证书来认证用户身份,认证成功后不需要使用SSL来进行访问。(可以配置多个security-constraint)
  • url-pattern:指定需要SSL才能进行访问的地址
  • transport-guarantee:合法值为NONE、 INTEGRAL或CONFIDENTIAL,transport-guarantee为NONE值将对所用的通讯协议不加限制。INTEGRAL值表示数据必须以一种防止截取它的人阅读它的方式传送。虽然原理上(并且在未来的HTTP版本中),在 INTEGRAL和CONFIDENTIAL之间可能会有差别,但在当前实践中,他们都只是简单地要求用SSL
  • 创建SSLServlet获取客户端证书

五、测试

  1. 用浏览器访问http://127.0.0.1:8080/SSL/SSLServlet,细心的读者可能发现链接已经跳转到了https://127.0.0.1:8443/SSL/SSLServlet ,这是由于这个地址被设置为需要SSL才能访问,所以跳转到了这个地址。访问时页面提示如下:

     

  由于我们这里是双向认证,所以也需要客户端的证书,我们接下来导入客户端证书:

  • 双击client.p12

  

  • 点击下一步

  

  • 一直点击下一步直到完成证书安装(按照提示进行操作即可)
  • 查看安装的客户端证书,由于我使用的Google Chrome浏览器(其他浏览器可能不同),设置 -> 高级设置 -> 管理证书

  

  

  2. 重新访问上面的地址:http://127.0.0.1:8080/SSL/SSLServlet

   

  浏览器提示选择客户端证书进行认证,我们点击【确定】,打开了一个警告页面,提示我们服务端证书不受信任

  

  而且地址栏的图标有个小红叉:

   

  当然我们直接点击是能打开的

  

  为了不出现这样的警告信息,我们可以导入服务器端证书到客户端

  a. 导入服务器端证书到客户端

    • 双击server.cer

      

    • 点击安装证书,然后选择证书的存储位置“受信任的根证书颁发机构”,一直点击下一步直到完成

      

    • 查看我们安装的服务器端证书

      

  b. 关闭浏览器,我们再访问

六、附录

  1. Keytool命令常用参数说明:
    • -genkeypair在用户主目录中创建一个默认文件”.keystore”,还会产生一个mykey的别名,mykey中包含用户的公钥、私钥和证书(在没有指定生成位置的情况下,keystore会存在用户系统默认目录)
    • -alias 产生别名 每个keystore都关联这一个独一无二的alias,这个alias通常不区分大小写
    • -keystore 指定密钥库的路径(产生的各类信息将不在.keystore文件中)
    • -keyalg 指定密钥的算法 (如 RSA,DSA,默认值为:DSA)
    • -validity 指定创建的证书有效期多少天(默认 90)
    • -keysize 指定密钥长度 (默认 1024
    • -storepass 指定密钥库的密码(获取keystore信息所需的密码)
    • -keypass 指定别名条目的密码(私钥的密码)
    • -dname 指定证书发行者信息 其中: “CN=名字与姓氏,OU=组织单位名称,O=组织名称,L=城市或区域名 称,ST=州或省份名称,C=单位的两字母国家代码”
    • -list 显示密钥库中的证书信息如:keytool -list -v –keystore path/to/keystore  -storepass password
    • -v 显示密钥库中的证书详细信息
    • -exportcert 导出指定别名的证书,如:keytool - exportcert -alias theAlias  -keystore path/to/keystore  -file path/to/keystore/cert  -storepass pass
    • -file 参数指定导出到文件的文件名
    • -delete 删除密钥库中某条目 keytool -delete -alias theAlias  -keystore path/to/keystore –storepass pass
    • -printcert 控制台打印证书的详细信息,如:keytool -printcert  -file path/to/keystore/cert -v
    • -keypasswd 修改密钥库中指定条目口令 keytool -keypasswd -alias theAlias -keypass oldPass -new newPass -storepass keystorePass -keystore path/to/keystore
    • -storepasswd 修改keystore口令 keytool -storepasswd -keystore path/to/keystore -storepass oldPass -new newPass
    • -importcert 将已签名数字证书导入密钥库 keytool -importcert -alias certAlias -keystore path/to/keystore  -file path/to/keystore/cert

  2.  本文源码下载

【完】

感谢您的阅读

tomcat配置SSL双向认证的更多相关文章

  1. Tomcat 配置 HTTPS双向认证

    Tomcat 配置 HTTPS 双向认证指引说明: � 本文档仅提供 Linux 操作系统下的指引 � 在阅读本指引前请您在 Linux 部署 JDK 和 Tomcatserver为了 Tomcat ...

  2. NGINX 配置 SSL 双向认证

    对于 NGINX 的 HTTPS 配置,通常情况下我们只需要实现服务端认证就行,因为浏览器内置了一些受信任的证书颁发机构(CA),服务器端只需要拿到这些机构颁发的证书并配置好,浏览器会自己校验证书的可 ...

  3. TOMCAT配置SSL认证为HTTPS协议服务

     1 . 问题概述 很多安全性要求较高的系统,都会使用安全套接字层(SSL)进行信息交换, Sun为了解决在Internet上的实现安全信息传输的解决方案.它实现了SSL和TSL(传输层安全)协议 ...

  4. linux下Tomcat+OpenSSL配置单向&双向认证(自制证书)

    背景 由于ios将在2017年1月1日起强制实施ATS安全策略,所有通讯必须使用https传输,本文只针对自制证书,但目前尚不确定自制证书是否能通过appstore审核. 1.必须支持传输层安全(TL ...

  5. Keytool配置 Tomcat的HTTPS双向认证

    Keytool配置 Tomcat的HTTPS双向认证 证书生成 keytool 简介 Keytool是一个Java数据证书的管理工具, Keytool将密钥(key)和证书(certificates) ...

  6. 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 ...

  7. nginx支持ssl双向认证配置

    nginx支持ssl双向认证配置 listen 443; server_name test.com; ssl on; ssl_certificate server.crt; //server端公钥 s ...

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

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

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

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

随机推荐

  1. Ado.net[登录,增删改查,Get传值,全选,不选,批量删除,批量更新]

    [虽然说,开发的时候,我们可以使用各种框架,ado.net作为底层的东西,作为一个合格的程序员,在出问题的时候我们还是要知道如何调试] 一.增删改查 cmd.ExecuteReader();执行查询, ...

  2. VS2015开发Android,自带模拟器无法调试、加载程序,算是坑吗

    VS2015出来后,确定变化很大,什么android.ios的,不在话下.对于我这样传统型的人,也第一时间试用了一下(vs2003->vs2008->vs2012->vs2015). ...

  3. 怎么才能算大项目(Application),大的衡量?

    最近在思考一个问题,就是怎么才算一个大型项目,大的衡量有哪些东西?为什么要搞清这个问题呢,是因为在实际的开发过程中,如果知道这是个多大的项目,那就有各种相应的解决方案(我们称之为套路的东西)就可以使用 ...

  4. OO方式下,ALV TREE和ALV GRID的不同之处

    作为大部分报表程序的基础,ALV GRID差不多是每个ABAP开发者必须了解和掌握的内容,因此网上也不乏相关资料,而ALV TREE的应用相对较少,中文资料也就比较少见了.实际上,ALV TREE和A ...

  5. Android开发4: Notification编程基础、Broadcast的使用及其静态注册、动态注册方式

    前言 啦啦啦~(博主每次开篇都要卖个萌,大家是不是都厌倦了呢~) 本篇博文希望帮助大家掌握 Broadcast 编程基础,实现动态注册 Broadcast 和静态注册 Broadcast 的方式以及学 ...

  6. 盘点国内11家已经获得融资的移动CRM平台

    盘点国内11家已经获得融资的移动CRM平台 亿欧网盘点了目前国内已经获得融资的11家移动CRM平台,它们分别是:纷享销客.红圈营销.小满科技.腾腾科技.麦客.美洽.销售易.快消总管.EC营客通.店小三 ...

  7. C# partial 學習筆記

    局部類的講解參考:http://blog.csdn.net/susan19890313/article/details/7575204 感謝作者~

  8. 地理数据库 (Geodatabase) 版本管理

    版本化地理数据库包含一些非版本化地理数据库中不存在的附加表格和记录.这些附加表和记录有助于长时间执行并行编辑.如果不进行版本化处理,则编辑者需要锁定数据并防止其他用户对数据进行编辑或查看.要使用此功能 ...

  9. iOS模态弹出半透明视图控制器

    项目中需要实现点击按钮出现的视图全屏覆盖,呈半透明状态可以看到下面的视图? 解决方案: 绕了很多弯路原来可以使用模态弹出一个视图控制器 在iOS8之后只需要设置一个最新的属性 SecondViewCo ...

  10. ViewPager+GridView实现横向滑动 仿大众点评

    先看演示效果: 1  ViewPager类提供了多界面切换的新效果. 新效果有如下特征: [1] 当前显示一组界面中的其中一个界面. [2] 当用户通过左右滑动界面时,当前的屏幕显示当前界面和下一个界 ...