SSL——Secure Sockets Layer

双向认证(个人理解):
客户端认证:
客户端通过浏览器访问某一网站时,如果该网站为HTTPS网站,浏览器会自动检测系统中是否存在该网站的信任证书,如果没有信任证书,浏览器一般会拒绝访问,IE会有一个继续访问的链接,但地址栏是红色,给予用户警示作用,即客户端验证服务端并不是强制性的,可以没有服务端的信任证书,当然是否继续访问完全取决于用户自己。如何去除地址栏的红色警告呢?后续会介绍导入服务端证书到浏览器的方法。

服务端认证:
服务端需要获取到客户端通过浏览器发送过来的认证证书,该证书在服务端的证书库中已存在,仅仅是个匹配过程,匹配成功即通过认证,可继续访问网站资源,反之则无法显示网页,后续有截图。

基本逻辑:
1、生成服务端**库并导出证书;
2、生成客户端**库并导出证书;
3、根据服务端**库生成客户端信任的证书;
4、将客户端证书导入服务端**库;
5、将服务端证书导入浏览器。

构建演示系统
演示环境:
JDK:1.6.0_32
Tomcat:apache-tomcat-7.0.27
开发工具:MyEclipse 10
浏览器:Internet Explorer 9

一、生成**库和证书
可参考以下**生成脚本,根据实际情况做必要的修改,其中需要注意的是:服务端的**库参数“CN”必须与服务端的IP地址相同,否则会报错,客户端的任意。
key.script
tomcat https 双向认证1、生成服务器证书库
tomcat https 双向认证
tomcat https 双向认证keytool -validity 365 -genkey -v -alias server -keyalg RSA -keystore E:\ssl\server.keystore -dname "CN=127.0.0.1,OU=icesoft,O=icesoft,L=Haidian,ST=Beijing,c=cn" -storepass 123456 -keypass 123456
tomcat https 双向认证
tomcat https 双向认证
tomcat https 双向认证2、生成客户端证书库
tomcat https 双向认证
tomcat https 双向认证keytool -validity 365 -genkeypair -v -alias client -keyalg RSA -storetype PKCS12 -keystore E:\ssl\client.p12 -dname "CN=client,OU=icesoft,O=icesoft,L=Haidian,ST=Beijing,c=cn" -storepass 123456 -keypass 123456
tomcat https 双向认证
tomcat https 双向认证
tomcat https 双向认证3、从客户端证书库中导出客户端证书
tomcat https 双向认证
tomcat https 双向认证keytool -export -v -alias client -keystore E:\ssl\client.p12 -storetype PKCS12 -storepass 123456 -rfc -file E:\ssl\client.cer
tomcat https 双向认证
tomcat https 双向认证
tomcat https 双向认证4、从服务器证书库中导出服务器证书
tomcat https 双向认证
tomcat https 双向认证keytool -export -v -alias server -keystore E:\ssl\server.keystore -storepass 123456 -rfc -file E:\ssl\server.cer
tomcat https 双向认证
tomcat https 双向认证
tomcat https 双向认证5、生成客户端信任证书库(由服务端证书生成的证书库)
tomcat https 双向认证
tomcat https 双向认证keytool -import -v -alias server -file E:\ssl\server.cer -keystore E:\ssl\client.truststore -storepass 123456
tomcat https 双向认证
tomcat https 双向认证
tomcat https 双向认证6、将客户端证书导入到服务器证书库(使得服务器信任客户端证书)
tomcat https 双向认证
tomcat https 双向认证keytool -import -v -alias client -file E:\ssl\client.cer -keystore E:\ssl\server.keystore -storepass 123456
tomcat https 双向认证
tomcat https 双向认证
tomcat https 双向认证7、查看证书库中的全部证书
tomcat https 双向认证
tomcat https 双向认证keytool -list -keystore E:\ssl\server.keystore -storepass 123456


二、Tomat配置
使用文本编辑器编辑${catalina.base}/conf/server.xml
找到Connector port="8443"的标签,取消注释,并修改成如下:
tomcat https 双向认证<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true"
tomcat https 双向认证               maxThreads
="150" scheme="https" secure="true"
tomcat https 双向认证               clientAuth
="true" sslProtocol="TLS"
tomcat https 双向认证               keystoreFile
="${catalina.base}/key/server.keystore" keystorePass="123456"
tomcat https 双向认证               truststoreFile
="${catalina.base}/key/server.keystore" truststorePass="123456"/>

备注:
keystoreFile:指定服务器**库,可以配置成绝对路径,如“D:/key/server.keystore”,本例中是在Tomcat目录中创建了一个名称为key的文件夹,仅供参考。
keystorePass:**库生成时的密码
truststoreFile:受信任**库,和**库相同即可
truststorePass:受信任**库密码

三、建立演示项目
项目结构图:
项目名称:SSL(随意)
tomcat https 双向认证

SSLServlet.java
tomcat https 双向认证package com.icesoft.servlet;
tomcat https 双向认证
tomcat https 双向认证import java.io.IOException;
tomcat https 双向认证import java.io.PrintWriter;
tomcat https 双向认证import java.security.cert.X509Certificate;
tomcat https 双向认证
tomcat https 双向认证import javax.servlet.ServletException;
tomcat https 双向认证import javax.servlet.http.HttpServlet;
tomcat https 双向认证import javax.servlet.http.HttpServletRequest;
tomcat https 双向认证import javax.servlet.http.HttpServletResponse;
tomcat https 双向认证
tomcat https 双向认证/**
tomcat https 双向认证 * <p>
tomcat https 双向认证 * SSL Servlet
tomcat https 双向认证 * </p>
tomcat https 双向认证 * 
tomcat https 双向认证 * 
@author IceWee
tomcat https 双向认证 * @date 2012-6-4
tomcat https 双向认证 * 
@version 1.0
tomcat https 双向认证 
*/

tomcat https 双向认证public class SSLServlet extends HttpServlet {
tomcat https 双向认证
tomcat https 双向认证    private static final long serialVersionUID = 1601507150278487538L;
tomcat https 双向认证    private static final String ATTR_CER = "javax.servlet.request.X509Certificate";
tomcat https 双向认证    private static final String CONTENT_TYPE = "text/plain;charset=UTF-8";
tomcat https 双向认证    private static final String DEFAULT_ENCODING = "UTF-8";
tomcat https 双向认证    private static final String SCHEME_HTTPS = "https";
tomcat https 双向认证
tomcat https 双向认证    public void doGet(HttpServletRequest request, HttpServletResponse response)
tomcat https 双向认证            throws ServletException, IOException {
tomcat https 双向认证        response.setContentType(CONTENT_TYPE);
tomcat https 双向认证        response.setCharacterEncoding(DEFAULT_ENCODING);
tomcat https 双向认证        PrintWriter out = response.getWriter();
tomcat https 双向认证        X509Certificate[] certs = (X509Certificate[]) request.getAttribute(ATTR_CER);
tomcat https 双向认证        if (certs != null{
tomcat https 双向认证            int count = certs.length;
tomcat https 双向认证            out.println("共检测到[" + count + "]个客户端证书tomcat https 双向认证");
tomcat https 双向认证            for (int i = 0; i < count; i++) {
tomcat https 双向认证                out.println("客户端证书 [" + (++i) + "]: ");
tomcat https 双向认证                out.println("校验结果:" + verifyCertificate(certs[--i]));
tomcat https 双向认证                out.println("证书详细:\r" + certs[i].toString());
tomcat https 双向认证            }

tomcat https 双向认证        }
 else {
tomcat https 双向认证            if (SCHEME_HTTPS.equalsIgnoreCase(request.getScheme())) {
tomcat https 双向认证                out.println("这是一个HTTPS请求,但是没有可用的客户端证书tomcat https 双向认证");
tomcat https 双向认证            }
 else {
tomcat https 双向认证                out.println("这不是一个HTTPS请求,因此无法获得客户端证书列表tomcat https 双向认证 ");
tomcat https 双向认证            }

tomcat https 双向认证        }

tomcat https 双向认证        out.close();
tomcat https 双向认证    }

tomcat https 双向认证
tomcat https 双向认证    public void doPost(HttpServletRequest request, HttpServletResponse response)
tomcat https 双向认证            throws ServletException, IOException {
tomcat https 双向认证        doGet(request, response);
tomcat https 双向认证    }

tomcat https 双向认证    
tomcat https 双向认证    /**
tomcat https 双向认证     * <p>
tomcat https 双向认证     * 校验证书是否过期
tomcat https 双向认证     * </p>
tomcat https 双向认证     * 
tomcat https 双向认证     * 
@param certificate
tomcat https 双向认证     * 
@return
tomcat https 双向认证     
*/

tomcat https 双向认证    private boolean verifyCertificate(X509Certificate certificate) {
tomcat https 双向认证        boolean valid = true;
tomcat https 双向认证        try {
tomcat https 双向认证            certificate.checkValidity();
tomcat https 双向认证        }
 catch (Exception e) {
tomcat https 双向认证            e.printStackTrace();
tomcat https 双向认证            valid = false;
tomcat https 双向认证        }

tomcat https 双向认证        return valid;
tomcat https 双向认证    }

tomcat https 双向认证
tomcat https 双向认证}

tomcat https 双向认证

web.xml
说明:该演示项目强制使用了SSL,即普通的HTTP请求也会强制重定向为HTTPS请求,配置在最下面,可以去除,这样HTTP和HTTPS都可以访问。
tomcat https 双向认证<?xml version="1.0" encoding="UTF-8"?>
tomcat https 双向认证<web-app version="3.0" 
tomcat https 双向认证    xmlns
="http://java.sun.com/xml/ns/javaee" 
tomcat https 双向认证    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance" 
tomcat https 双向认证    xsi:schemaLocation
="http://java.sun.com/xml/ns/javaee 
tomcat https 双向认证    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
>
tomcat https 双向认证      <display-name>Secure Sockets Layer</display-name>    
tomcat https 双向认证    
tomcat https 双向认证    <servlet>
tomcat https 双向认证        <servlet-name>SSLServlet</servlet-name>
tomcat https 双向认证        <servlet-class>com.icesoft.servlet.SSLServlet</servlet-class>
tomcat https 双向认证    </servlet>
tomcat https 双向认证    <servlet-mapping>
tomcat https 双向认证        <servlet-name>SSLServlet</servlet-name>
tomcat https 双向认证        <url-pattern>/sslServlet</url-pattern>
tomcat https 双向认证    </servlet-mapping>
tomcat https 双向认证    
tomcat https 双向认证    <welcome-file-list>
tomcat https 双向认证      <welcome-file>index.jsp</welcome-file>
tomcat https 双向认证    </welcome-file-list>
tomcat https 双向认证
tomcat https 双向认证    <!-- 强制SSL配置,即普通的请求也会重定向为SSL请求 -->  
tomcat https 双向认证    <security-constraint>
tomcat https 双向认证        <web-resource-collection>
tomcat https 双向认证            <web-resource-name>SSL</web-resource-name>
tomcat https 双向认证            <url-pattern>/*</url-pattern><!-- 全站使用SSL -->
tomcat https 双向认证        </web-resource-collection>
tomcat https 双向认证        <user-data-constraint>
tomcat https 双向认证            <description>SSL required</description>
tomcat https 双向认证            <!-- CONFIDENTIAL: 要保证服务器和客户端之间传输的数据不能够被修改,且不能被第三方查看到 -->
tomcat https 双向认证            <!-- INTEGRAL: 要保证服务器和client之间传输的数据不能够被修改 -->
tomcat https 双向认证            <!-- NONE: 指示容器必须能够在任一的连接上提供数据。(即用HTTP或HTTPS,由客户端来决定)-->
tomcat https 双向认证            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
tomcat https 双向认证        </user-data-constraint>
tomcat https 双向认证    </security-constraint>
tomcat https 双向认证</web-app>


index.jsp
tomcat https 双向认证<%@ page language="java" pageEncoding="UTF-8"%>
tomcat https 双向认证
tomcat https 双向认证<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
tomcat https 双向认证<html>
tomcat https 双向认证<head>
tomcat https 双向认证<title>客户端证书上传</title>
tomcat https 双向认证<meta http-equiv="pragma" content="no-cache">
tomcat https 双向认证<meta http-equiv="cache-control" content="no-cache">
tomcat https 双向认证<meta http-equiv="expires" content="0">    
tomcat https 双向认证</head>
tomcat https 双向认证<body>
tomcat https 双向认证<form action="${pageContext.request.contextPath}/sslServlet" method="post">
tomcat https 双向认证    <input type="submit"  value="提交证书"/>
tomcat https 双向认证</form>
tomcat https 双向认证</body>
tomcat https 双向认证</html>


四、演示及配置
发布演示项目,通过浏览器访问:http://127.0.0.1:8080/SSLhttps://127.0.0.1:8443/SSL,得到相同的结果,如图:

tomcat https 双向认证

tomcat https 双向认证


得到如上结果的原始是因为客户端没有通过服务端的安全认证,接下来将服务端给客户端颁发的证书导入到浏览器中:
双击“client.p12”
tomcat https 双向认证


弹出窗口,下一步
tomcat https 双向认证


默认,下一步
tomcat https 双向认证


输入生成**时的密码“123456”,下一步
tomcat https 双向认证


下一步
tomcat https 双向认证


完成
tomcat https 双向认证


成功
tomcat https 双向认证


再次访问http://127.0.0.1:8080/SSLhttps://127.0.0.1:8443/SSL,弹出提示框:
tomcat https 双向认证


点击确定后,IE浏览器自动阻止了继续访问,并给予警告提示,原因是浏览器中未导入该网站的可信证书
tomcat https 双向认证

tomcat https 双向认证


点击“继续浏览此网站”,弹出提示,点击确定
tomcat https 双向认证


哇!鲜红的地址栏,够醒目吧!你访问的网站不安全那,亲!
tomcat https 双向认证


点击“提交证书”按钮,返回正确结果!
tomcat https 双向认证


可以看出,客户端并没有服务端那么严格,只要未通过验证就甭想访问,下面将服务端生成的信任证书导入到浏览器的根证书中,这样红色的地址栏就会消失了!
开始导入服务端信任证书,不能双击“server.cer”,需要手动导入到受信任的根证书机构中去。
tomcat https 双向认证


浏览器Internet选项-内容-证书
tomcat https 双向认证


点击“受信任的根证书颁发机构”
tomcat https 双向认证


点击“导入”
tomcat https 双向认证


下一步
tomcat https 双向认证


手动选择“server.cer”,下一步


tomcat https 双向认证



下一步
tomcat https 双向认证


完成
tomcat https 双向认证


点“是”

tomcat https 双向认证


成功
tomcat https 双向认证




可以看到我们刚刚导入的根证书
tomcat https 双向认证


把所有浏览器窗口都关掉,再次访问网站,发现鲜红色已经逝去
tomcat https 双向认证


点击“提交证书”按钮,一切正常了,双向认证的DEMO结束了!

tomcat https 双向认证

原文地址:http://www.blogjava.net/icewee/archive/2012/06/04/379947.html


常见问题按照以上操作,IE上是没有问题的,但是在火狐和谷歌上有问题,报域名错误missing_xxxxnames


解决方案:在生成服务端的证书时加上域名,具体如下:

keytool -validity 365 -genkey -v -alias server -keyalg RSA -keystore E:\ssl\server.keystore -dname "CN=127.0.0.1,OU=icesoft,O=icesoft,L=Haidian,ST=Beijing,c=cn" -storepass 123456 -keypass 123456  -ext san=dns:test.example.com,ip:172.18.1.171


其中:test.example.com要在C:\Windows\System32\drivers\etc下面的hosts文件中配置

        172.18.1.171    test.example.com

到此完美解决。




相关文章:

  • 2021-07-16
  • 2022-12-23
  • 2021-04-08
  • 2022-12-23
  • 2021-11-20
  • 2022-01-08
  • 2022-01-08
猜你喜欢
  • 2021-11-20
  • 2021-09-24
  • 2022-01-08
  • 2021-05-27
  • 2022-01-08
  • 2022-12-23
  • 2021-11-20
相关资源
相似解决方案