实现在 Linux 下 Tomcat 的双向SSL认证-程序员宅基地

技术标签: java  web.xml  操作系统  

实现在 Linux 下 Tomcat 的双向SSL认证

 

一、前言:

  关于如何使用Tomcat服务器实现双向SSL认证的文章很早就有了, 比较实用的文章可以看看 IBM developerWorks 中国网站 2002年5月 配置Tomcat 4使用双向SSL(http://www-900.ibm.com/developerWorks/cn/security/se-tcssl/index.shtml )以及 配置Tomcat 5使用双向SSL (http://thinkbase.net/w/main/Wiki?Tomcat5SSL_ServerAndClient)。

      关于原理方面不是本文的重点,故下面只讲解实际操作的过程以及每个过程的说明:


二、需要的软件包:

       Tomcat 5.0.25
       用途:Web Server。 
      下载: http://jakarta.apache.org/builds/jakarta-tomcat-5.0/release/v5.0.25/bin/

       JSSE 1.0,2 
       用途:用来产生Tocmcat使用的秘钥对(keystore)。 在 JDK 1.4以上版本 中已经自带了这个工具, 因此, 只需要安装 JDK1.4.x 即可 
       下载: http://java.sun.com/products/jsse/

       Openssl 0.9.9.6 
       用途:用来产生CA证书、签名并生成IE可导入的PKCS#12格式私钥。 
       下载: http://www.openssl.org/

       以上工具的安装过程可以参考自带的帮助,本文就不再详细描述了。


三、证书环境设置:

export CA_DN=/C=CN/ST=GuangDong/L=GuangZhou/O=boss ssl/OU=Boss CACenter/CN=Boss CA Root/[email protected]

export SERVER_DNAME=CN=21cn.com,OU=Boss Server,O=boss ssl,L=GuangZhou,ST=GuangDong,C=CN
export SERVER_KEYPASS=openssl
export SERVER_STOREPASS=openssl
export SERVER_ALIAS=boss-alias
export SERVER_KEYSTORE=boss-alias.keystore

export CLIENT_DN_OU=W21cn-boss-client
export CLIENT_DN_CN=Huronghua
export CLIENT_DN=/C=CN/O=W21cn Boss/OU=$CLIENT_DN_OU/CN=$CLIENT_DN_CN

export SSL_JAVA_HOME=/home/uud/software/jdk1.5.0_06
export JDK_KEYSTORE=$SSL_JAVA_HOME/jre/lib/security/cacerts

#JSSE 信任的CA根证书的存储密码, 似乎不能改变
export JDK_STOREPASS=changeit

export OPENSSL_SRL_FILE=./ca-cert.srl
export CA_ROOT_ALIAS=Boss-CA-ROOT


四、生成CA私钥以及自签名根证书, 最后得到PKCS12格式的CA根证书: 

说明:
该命令生成CA私钥以及自签名根证书, 最后得到PKCS12格式的CA根证书(PKCS12格式的CA根证书受密码保护, 因此有比较好的安全性); 
生成的PKCS12格式的CA根证书保存在 dist\ca-cert 目录下, 在正式使用的系统中, 这个证书文件(*.pfx)需要妥善保存, 
因为以后的服务器证书和客户端证书都需要依赖这个证书, 尤其是客户端证书, 如果丢失了CA根证书, 
就无法发布新的客户端证书了, 而重新生成CA根证书, 则需要重新生成服务器证书和客户端证书, 
在客户端用户较多的情况下, 重新发布所有的客户端证书是有相当大的工作量; 
在执行这个命令的过程中, 会提示输入证书保护密码, 请注意不要遗忘或者泄漏这个密码, 否则根证书的安全会受到威胁. 

mkdir ca
mkdir dist
cd dist
mkdir ca-cert
cd ..


# genrsa [产生密钥命令] -out[密钥文件输出路径] 1024 [密钥位数]
openssl genrsa -out ca/ca-key.pem 1024

# req[产生证书命令] -new[新生成] -out[证书文件输出路径] -key[私钥文件路径]

openssl req -new -out ca/ca-req.csr -key ca/ca-key.pem -subj $CA_DN

# x509[签发x509证书命令] -req[输入待签发证书] -in[输入待签发证书文件路径] -out[产生x509证书文件输出路径]
# -signkey[自签发密钥文件路径] -days[证书有效期]
openssl x509 -req -in ca/ca-req.csr -out ca/ca-cert.pem -signkey ca/ca-key.pem -days 365

# 生成CA证书: ca/ca-cert.pfx, 注意一定要记住导出密码:默认为 ssl
# pkcs12[生成PKCS12格式证书命令] -export[导出文件] -clerts[仅导出client证书] -password[导出密码]
# -in[输入的client证书文件路径] -inkey[client证书密钥文件路径] -out[导出PKS12格式文件路径]

openssl pkcs12 -export -clcerts -in ca/ca-cert.pem -inkey ca/ca-key.pem -out ca/ca-cert.pfx

# 将生成的证书保存起来(以后需要用到)
cp ca/ca-cert.pfx dist/ca-cert/ca-cert-200606.pfx

      


五、从PKCS12格式的CA根证书导出 CA私钥和未加密CA根证书

说明:
该命令用于从PKCS12格式的CA根证书中导出CA私钥和未加密CA根证书; 
由于安全原因, CA根证书平时以密码保护的PKCS12格式文件(*.pfx)存放, 
那么如果需要使用CA根证书来发布服务器证书或者客户端证书时, 首先需要执行这个命令得到CA根证书的未加密形式; 
在执行这个命令的过程中, 会出现两次提示输入根证书的保护密码, 如果密码不正确, 这个命令将不能执行成功, 
也就无法进行下面两步的发布证书的操作了.

mkdir decrypt_ca

# 从PKCS12格式的CA证书导出不加密的CA证书: ca\ca-cert.pem
openssl pkcs12 -in dist/ca-cert/ca-cert-20060621.pfx -clcerts -nodes -nokeys -out decrypt_ca/ca-cert.pem

# 将得到的证书文件的开头四行(Bag Attributes)去掉
# 因为step2-server.bat中keytool import时会认为含有Bag Attributes的文件"不是一个 X.509 认证"

vi ca-cert.pem 
先按 4,再按 dd
最后按 x! 退出文件编辑

# 从PKCS12格式的CA证书导出CA私钥: ca\ca-key.pem
openssl pkcs12 -in dist/ca-cert/ca-cert-20060621.pfx -clcerts -nodes -out decrypt_ca/file.pem
openssl rsa -in decrypt_ca/file.pem -out decrypt_ca/ca-key.pem

   


六、生成服务器端证书

说明:
该命令用于生成服务器端证书(keystore文件); 
注意: CA根证书同时也会被导入到证书的keystore文件中, 这样在将这个证书应用到Tomcat Web服务器上的时候就不需要将CA根证书
导入到JSSE的默认位置了; 
这个命令必须在执行 (五、从PKCS12格式的CA根证书导出 CA私钥和未加密CA根证书) 之后才能正常运行.

生成KeyPair
mkdir server


# -genkey[产生密钥对] -alias[密钥对别名] -validity[密钥有效期] -keyalg[密钥算法参数] -keysize[密钥位数]
# -keypass[密钥保护密码]- storepass[存储密码]
# -dname[别名相关附加信息,其中cn是服务器的名字一定要与WEB服务器中设置的一样] -keystore[密钥存储文件路径]

keytool -genkey -alias $SERVER_ALIAS -validity 720 -keyalg RSA -keysize 1024 -keypass $SERVER_KEYPASS -storepass $SERVER_STOREPASS -dname $SERVER_DNAME -keystore server/$SERVER_KEYSTORE


生成待签名证书 server/server.csr
# -certreq[产生待签名证书] -alias[证书别名] -sigalg[证书算法参数] -file [产生文件输出路径]
# -keypass[密钥保护密码] -keystore[存储文件路径] -storepass[存储密码]

keytool -certreq -alias $SERVER_ALIAS -sigalg MD5withRSA -file server/server.csr -keypass $SERVER_KEYPASS -keystore server/$SERVER_KEYSTORE -storepass $SERVER_STOREPASS


用CA私钥进行签名, 产生x509证书文件

# x509[签发x509证书命令] -req[输入待签发证书] -in[输入待签发证书文件路径] -out[产生x509证书文件输出路径]
# -CA[签发根证书] -CAkey[根证书密钥文件] -days[证书有效期] -CAserial[CA序列号文件]

openssl x509 -req -in server/server.csr -out server/server-cert.pem -CA decrypt_ca/ca-cert.pem -CAkey decrypt_ca/ca-key.pem -days 365 -CAserial $OPENSSL_SRL_FILE -sha1 -trustout


导入(替换)信任的CA根证书到JSSE的默认位置(%JDK_KEYSTORE%)


# 导入前首先删除(如果原来已经导入过)
# JSSE 信任的CA根证书的密钥存储文件路径
keytool -delete -v -alias $CA_ROOT_ALIAS -storepass $JDK_STOREPASS -keystore $JDK_KEYSTORE

# -import[导入命令] -v trustcacerts[导入信任证书] -storepass[存储密码] -alias[CA根证书的别名]
# -file[证书文件路径] -keystore[导入文件路径] -noprompt[不提示"信任这个认证?"]

keytool -import -v -trustcacerts -storepass $JDK_STOREPASS -alias $CA_ROOT_ALIAS -file decrypt_ca/ca-cert.pem -keystore $JDK_KEYSTORE


把CA签名后的server端证书导入keystore: server/%SERVER_KEYSTORE%
# -import[导入命令] -v trustcacerts[导入信任证书] -storepass[存储密码] -keypass[密钥保护密码]
# -alias[服务器证书的别名] -file[证书文件路径] -keystore[导入文件路径]

keytool -import -v -trustcacerts -storepass $SERVER_STOREPASS -keypass $SERVER_KEYPASS -alias $SERVER_ALIAS -file server/server-cert.pem -keystore server/$SERVER_KEYSTORE

把CA根证书导入keystore: server/%SERVER_KEYSTORE%
# -import[导入命令] -v trustcacerts[导入信任证书] -storepass[存储密码] -keypass[密钥保护密码]
# -alias[服务器证书的别名] -file[证书文件路径] -keystore[导入文件路径] -noprompt[不提示"您仍然想要将它添加到自己的keystore 吗?"]

keytool -import -v -trustcacerts -storepass $SERVER_STOREPASS -keypass $SERVER_KEYPASS -alias $CA_ROOT_ALIAS -file decrypt_ca/ca-cert.pem -keystore server/$SERVER_KEYSTORE


查看JSSE CA根证书
keytool -list -storepass $JDK_STOREPASS -keystore $JDK_KEYSTORE -alias $CA_ROOT_ALIAS -v

删除导入到JSSE的默认位置的CA根证书(使JDK恢复原状)
keytool -delete -v -alias $CA_ROOT_ALIAS -storepass $JDK_STOREPASS -keystore $JDK_KEYSTORE


将生成的证书保存起来(供服务器使用)
cd dist
mkdir server
cd ..
cp server/$SERVER_KEYSTORE dist/server/$SERVER_KEYSTORE

查看server端证书
keytool -list -storepass $SERVER_STOREPASS -keystore dist/server/$SERVER_KEYSTORE -v


七、发布客户端证书: 

说明:
这个命令用于发布客户端证书; 
为了便于批量生成客户端证书, 这个命令支持命令行参数, 第1到3个参数依次为: 
客户端证书的名称(Common Name) 
客户端证书所属的组织(Organizational Unit Name) 
产生的PKS12格式客户端证书的导入密码, 这个密码可以保护证书只能被知道密码的用户导入到浏览器
这个命令必须在执行 (五、从PKCS12格式的CA根证书导出 CA私钥和未加密CA根证书) 之后才能正常运行.

mkdir client

cd dist
mkdir client
cd ..

# 生成client私钥: client/client-key.pem
# genrsa [产生密钥命令] -out[密钥文件输出路径] 1024 [密钥位数]

openssl genrsa -out client/client-key.pem 1024


生成待签名证书: client/client-req.csr

# req[产生证书命令] -new[新生成] -out[证书文件输出路径] -key[私钥文件路径]
# -subj[request's subject, 这里放置Distinguished Name(DN)信息]

openssl req -new -out client/client-req.csr -key client/client-key.pem -subj $CLIENT_DN


用CA私钥进行签名, 产生x509证书文件: client/client.crt
# x509[签发x509证书命令] -req[输入待签发证书] -in[输入待签发证书文件路径] -out[产生x509证书文件输出路径]
# -signkey [密钥文件路径]
# -CA[签发根证书] -CAkey[根证书密钥文件] -days[证书有效期] -CAserial[CA序列号文件]

openssl x509 -req -in client/client-req.csr -out client/client.crt -signkey client/client-key.pem -CA decrypt_ca/ca-cert.pem -CAkey decrypt_ca/ca-key.pem -days 365 -CAserial $OPENSSL_SRL_FILE

生成client端的个人证书: client/$_CLIENT_P12_FILE

# pkcs12[生成PKS12格式证书命令] -export[导出文件] -clerts[仅导出client证书] -password[导出密码]
# -in[输入的client证书文件路径] -inkey[client证书密钥文件路径] -out[导出PKS12格式文件路径]
# -name[好记的名字]

密码是 clientssl
openssl pkcs12 -export -clcerts -in client/client.crt -inkey client/client-key.pem -out client/$CLIENT_DN_OU-$CLIENT_DN_CN.p12 -name $CLIENT_DN_OU-$CLIENT_DN_CN

将生成的证书保存起来(发布给用户)
cp client/$CLIENT_DN_OU-$CLIENT_DN_CN.p12 dist/client/$CLIENT_DN_OU-$CLIENT_DN_CN.p12


八、Tomcat 5 服务器配置: 

参考配置方法如下:
将 "六、生成服务器端证书" 命令产生的 dist\server 目录下的 keystore 文件(如果使用默认配置, 这个文件叫做"boss-alias.keystore")复制到 Tomcat 安装目录的 conf 目录下; 
修改 Tomcat 安装目录的 conf 目录下的 "server.xml" 文件, 修改 <Service name="Catalina"> 包含的 "Connector" 元素, 示例如下(仅供参考): 

<Connector port="8443" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
URIEncoding="UTF-8"
keystoreFile="%Tomcat%/conf/boss-alias.keystore"
keystorePass="openssl"
truststoreFile="%Tomcat%/conf/boss-alias.keystore"
truststorePass="openssl"/>


九、启用双向 SSL 时 Web 应用程序的配置 : 

       要启用双向 SSL 认证, 在 Web 应用程序的 web.xml 中需要如下增加一些配置: auth-method=CLIENT-CERT 说明是"以客户端数字证书来确认用户的身份", transport-guarantee=CONFIDENTIAL 表示应用程序要求数据必须在一种"防止其他实体看到传输的内容的方式中传送".. 

<login-config>
<!-- Authorization setting for SSL -->
<auth-method>CLIENT-CERT</auth-method>
<realm-name>Client Cert Users-only Area</realm-name>
</login-config>
<security-constraint>
<!-- Authorization setting for SSL -->
<web-resource-collection >
<web-resource-name >SSL</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>


十、编写 JSP 页面显示 证书的内容: 

      经过以上的配置之后, 那么即使用户是通过 http 访问 Web 应用程序的, 浏览器也会自动切换到 https 方式并弹出选择客户端证书的对话框.
如何使用客户端证书进行用户验证

        在 web 应用程序中, 可以通过 java 代码从 request 对象中获得, 根据 Servlet Specifications, 使用request.getAttribute("javax.servlet.request.X509Certificate") 就可以得到 https 请求的客户端证书链信息, 其中第一个元素就是客户端证书, 相应的示例代码如下:

<%@ page import="java.security.cert.X509Certificate"%>
<%
//response.sendRedirect("jsp/vpay/input.jsp");
String certSubject = null;
java.security.cert.X509Certificate[] certChain=
(java.security.cert.X509Certificate[])
request.getAttribute("javax.servlet.request.X509Certificate");
if (null!=certChain){
int len=certChain.length;
if (len>0){
java.security.cert.X509Certificate cert =
(java.security.cert.X509Certificate)certChain[0];
java.security.Principal pSubject = cert.getSubjectDN();
certSubject = pSubject.getName();
}
}
%>
Subject = <%=certSubject%>

 

十一、导入客户端证书并访问 HTTPS 应用: 

       导入客户端证书到浏览器中(双击客户端证书文件 "W21cn-boss-client-Huaronghu.p12" 即可导入 IE)。

      导入完毕后, 启动 Tomcat, 可以看到 http://localhost:8080/index.jsp 内容的访问则会自动切换到 https://localhost:8443 上去了; 同时可以看到, 使用 HTTPS 方式访问时, 客户端证书的 Subject 可以被 jsp 页面获得。

        试着在浏览器里面把导入的证书删除, 你会发现 网站的内容已经不能访问了:


十二、总结: 

      当Web服务器开始正式运行以后, "四、生成CA私钥以及自签名根证书, 最后得到PKCS12格式的CA根证书" 命令是不能再次执行的, 
如果需要重新发布服务器证书, 或者发布新的客户端证书,
在执行 “六、生成服务器端证书” 和 “七、生成客户器端证书” 命令前, 
可以通过 “五、从PKCS12格式的CA根证书导出 CA私钥和未加密CA根证书”重新从保存的PKCS12格式CA根证书中导出CA私钥和未加密CA根证书.

转载于:https://my.oschina.net/zhanghuibo/blog/650403

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/chicaishi3429/article/details/100851008

智能推荐

8.S5PV210之RTC实时时钟代码_s5pv210 rtc 驱动-程序员宅基地

文章浏览阅读649次。RTC.h:RTC.c:main.c_s5pv210 rtc 驱动

零基础学AI,轻松搞定人工智能6大方向【附资料】_搞定ai-程序员宅基地

文章浏览阅读4.5k次。在当前这个市场最不缺的是资料,不缺的原因是因为市场大量泛滥着各种姿势的学习资料;最缺的也是资料,缺的原因是因为真正有体系,有价值的资料少之又少。所以,我们送你一份价值2980的学习路线图+AI课程资料+线上直播课学习,这些资料足够你入门AI领域!添加CSDN小姐姐仅限500人!领取价值2980人工智能学习路线图+课程资料+视频资料AI初级应用工程师的完整学习路径图~添加CSDN小姐姐仅限500人!领取价值2980人工智能学习路线图+课程资料+视频资料._搞定ai

以算法岗为例:我最想对入职前的自己说些什么?-程序员宅基地

文章浏览阅读251次。来自:机器学习与推荐系统进入算法岗的正式工作虽然只有半年多,但从 19 年 1 月就在算法岗开始实习,算下来到现在都有两年多的工作经验了,不过正式参加工作以后还是有了很多新的感悟,这篇文章..._算法岗入职很紧张

2017 Wuhan University Programming Contest (Online Round) D. Events,线段树区间更新+最值查询!...-程序员宅基地

文章浏览阅读87次。D. Events 线段树区间更新查询区间历史最小值,看似很简单的题意写了两天才写出来。 题意:n个数,Q次操作,每次操作对一个区间[l,r]的数同时加上C,然后输出这段区间的历史最小值。 思路:在线段树区间更新最值查询的基础上再用一个变量表示...

5V过压保护电路原理解说-程序员宅基地

文章浏览阅读8.7k次,点赞13次,收藏99次。百度许久,发现这个保护电路是有,但相关的原理描述却很空白,或者描述的有点让人懵逼……因此写此文章记录一下使用心得。如图所示。当VIN电压大于稳压二极管电压时,SS8550两端存在正向压降,PNP管导通。导通的电压将PMOS管两端的GS电压相等,压降抵消,另其无法导通,VOUT输出停止。当VIN电压小于等于稳压二极管电压时,SS8550不导通,此时PMOS管的2脚电压为7V,1脚电压下拉接地,为0V,GS两端存在正向压降,导通,输出电压。要点1:稳压二极管在此电路中的作用? 作用就..._5v过压保护电路

【程序】猫狗分类程序:包括网络结构、数据集处理、训练、测试-程序员宅基地

文章浏览阅读597次。网络的输出层设置两个神经元的原因:神经网络有两个输出值对应两种类别,通过学习数据的不同特征,让两种类别在输出上有体现,即0趋近于猫,1趋近于狗。宏观上来看,神经网络具有了辨识猫狗的能力。训练过程中,有对GT由一维处理成二维的操作,目的也是为了和神经网络二维的输出进行匹配。import torchimport osimport numpy as npfrom PIL import Imagefrom torch.utils.data import Dataset, DataLoade..

随便推点

【转载】笔记:计算机_体系结构_操作系统_软件_操作系统内核_GNU_Linux_C_Python_Latex_Java_TCP/IP_MacOS_Windows这些词语的历史,关系-程序员宅基地

文章浏览阅读381次。一、计算机的发明世上本无路,走的人多了,就有了路。世上本无计算机,琢磨的人多了……没有计算机,一切无从谈起。三个人对计算机的发明功不可没,居功至伟。阿兰·图灵(Alan Mathison Turing)、阿塔那索夫(John Vincent Atanasoff)、和冯·诺依曼(John von Neumann)。图灵从理论上证明了计算机的可行性;阿塔那索夫实践了图灵的理论;冯·诺依曼奠...

c语言json写配置文件,在C语言中解析json配置文件-程序员宅基地

文章浏览阅读411次。业务需求在C或者C++项目中常常需要解析配置文件,我们常见的配置文件格式一般就是.ini,xml,lua或者是一般的text文件,这些格式比较恼人的一个问题就是数据格式过于冗余,或者功能不够强大,不支持正则匹配,或者实现解析文件的代码过多,效率不高等等。比较大型的开源项目,比如Nginx,ATS等都有自己比较庞大的配置文件格式,特别是Nginx,语言十分独特简洁,功能强大,但是往往代码较为繁杂。那..._c语言配置文件一般用什么格式

【Java并发编程】FutureTask 阻塞等待异步结果_java futuretask会阻塞吗-程序员宅基地

文章浏览阅读1.9k次。什么是FutureTaskFutureTask类实现了RunnableFuture接口,RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以FutureTask 既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。怎么用FutureTask由介绍可知,FutureTa..._java futuretask会阻塞吗

ZVM – 记VMP保护代码还原工程_zvm vmp-程序员宅基地

文章浏览阅读1.6w次,点赞6次,收藏27次。1. 前言. 这篇文章写于2012年的8月,ZVM这个工程是我于2007年左右,一时头脑发晕而做的项目.做的时候是有考虑将其加密解密作为商业化运营的,如果失败,就当是体验一下这种所谓的CRACK界最强,也是最后一道防御是什么样子的.或者还能自己实现一套类似的软件.不管怎么说,研究VMP前后大约花掉我半年多的业余时间(最早还是个CONSOLE工程),还原引擎包含了VM指令调试器,_zvm vmp

Nginx启动报[10013]错误_nginx 错误1053-程序员宅基地

文章浏览阅读601次。原因: 80端口被占用cmd中查看80端口的占用情况:发现果然被占用,PID为4的进程占用,随后打开进程管理器发现是System进程占用80端口的情况 IIS服务器SqlServer数据库解决方法:关闭占用80端口的进程..._nginx 错误1053

局部图像描述子_图像局部特征描述子-程序员宅基地

文章浏览阅读314次。提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结前言提示:这里可以添加本文要记录的大概内容:例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。提示:以下是本篇文章正文内容,下面案例可供参考一、pandas是什么?示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。二、使用步骤1.引入库代码_图像局部特征描述子

推荐文章

热门文章

相关标签