Tomcat实现https双向认证配置
- 6.1创建证书库
- 6.2导出根证书
- 6.3证书库发起请求
- 6.4跟证书库对请求签名
- 6.5根证书添加信任
- 6.6签名文件添加信任
- 6.7证书库导出cer
- 6.8 cer生成临时证书库
- 6.9从临时证书库导出p12
注意:本文偏重于实际操作,理论部分请自行掌握。
注意:所有的代码不可换行,在命令提示符中一行完成。
环境:window 7
注意:jdk版本–jdk1.8(1.7未测试,不过jdk6038这个版本一定不可以。因为使用根证书进行签名,这个版本的jdk没有对应的命令,可能是还不支持。不过,签名这一步可以在其他的环境中完成。生成证书的每一步分理论上都可以在独立的环境中完成。)
1.生成证书库
首先,根证书就是给别的证书签名的证书,根证书的职责就是与CA做同样的事情,确认其他的证书是否可信,如果可信,进行签名。
结果(密码最少6位)
解释一下:
各位把keystore当做数据库,basic当做表就比较容易理解了。上面的命令使用类比数据库的方式来解释:
keytool表示使用java_home中的bin中的keytool.exe这个程序
-genkey表示新建一个密钥对–新建一个数据库
-alias表示数据库中新建一个表
basic是数据库中的一张表的名字
-keyalg数据库中数据加密的方式
dsa一种加密方法
-keysize加密长度
1024字节
-sigalg签名的加密方式
dsa加密方式
-startdate数据库开始(创建)时间(ps:时间格式yyyy/mm/dd,还可以加上具体的时间不过在oracle官网中没有给出具体的例子keytool官网文档传送门)
-validity有效时间
365(天)
-keystore创建数据库(证书库)
H:\basic.keystore(路径和文件名字,其实文件的后缀隐士的给出了证书库的格式jks,其他的请在官网查找)
-storepass数据库的密码
-keypass数据库表的密码
2.jks转p12
结果:
说明:
-importstore 使用导入证书库功能
-srckeystore源证书库
-destkeystore目标证书库(后缀表示格式-storetype具体查看文档,不过使用后缀更加简单,本来命令就很长了。)
-srcstorepass源证书库的密码
-deststorepass目标证书库的密码
主密码:证书库条目的密码(数据库表的密码)
此时在目标位置生成了一个basic.p12的证书库,p12可以在大多数的浏览器中导入。
3.证书库导出cer文件
首先使用查看命令查看证书库,看看有哪些条目(表)
结果:
说明:
-v详细输出
-list查看
接下来获得cer文件
此时生成了basic.cer文件,cer文件是给window用来安装证书的(ps:linux以后有时间补充)
4.证书库生成证书请求
此时会生成一个cer文件,安装提示无效的证书。
证书请求就是需要发送给ca或者第三方请求签名的文件。
5.对证书请求进行签名
此时会生成一个新的cer文件,这个文件就是签名后的文件。
说明:服务器发起请求,生成请求文件,第三方对请求文件进行签名,服务器把第三方的证书添加到可信列表,然后对签名后的文件添加可信链表,此时,就会形成一个信任链。
服务器信任第三方,签名后的文件来源于第三方,所以,信任签名后的文件。然后呢,我们的服务器也可以进行签名,这样,对于每一个证书,都可以追溯其源头,形成信任链。
这也是为什么ca是根证书认证中心。
以上命令执行无任何问题,但是,可能由于某些参数设置的问题,导致生成的证书不可用。所以,上面只是命令的解析,后面会有一个完整的例子。
6.例子
6.1创建证书库
6.2导出根证书
6.3证书库发起请求
6.4跟证书库对请求签名
6.5根证书添加信任
6.6签名文件添加信任
6.7证书库导出cer
6.8 cer生成临时证书库
6.9从临时证书库导出p12
7.证书安装
上述命令正确执行后生成的文件
安装根证书
basic.cer
安装client.cer
但是如果卸载掉之前装的basic.cer
使用win+R运行certmgr.msc
第二个basic就是之前安装的,第一个是我自己测试的时候安装的。右键删除basic证书。
此时安装client.cer
很明显,有警告提示了。如果你能把自己basic.cer直接在操作系统层面,从计算机出厂就默认安装,那么,你就有和ca同样的权利,使用basic进行签名的证书,都不会有警告。这也是正规证书和野证书的区别。正规证书是我们一开始安装client.cer的情况,野证书会有提示。
这也是我们为什么要大费周折的创建一个basic证书库,因为把basic证书库自己添加到可信任机构,那么由basic签名的证书都不会提示。
接下来安装p12文件(未安装basic)
提示输入密码,这个密码是哪里设置的?
这里的deststorepass的值就是上面图片需要的密码。
现在查看一下服务器证书库,客户端证书库,跟证书库的情况:
根证书库:
总结一下:
basic:----------key_basic------所有者basic------发布者basic-----链长度1
server:----key_basic-------所有者basic------发布者basic
-------key_server---------链长度2-------所有者server-----发布者basic
链接到key_basic
client:----key_client------所有者basic------发布者basic
------key_client-----链长度2-----所有者client-----发布者basic
8.客户端服务端增加相互信任
服务器证书库添加信任客户端证书(增加一张表)
客户端证书库添加信任服务端证书
9.tomcat设置
Tomcat安装目录下的conf文件夹中的server.xml文件中加入
注意反斜杠
然后启动
注意:这里有一个坑----
先不要用bin目录下的startup,先使用configtest,测试一下,会发现报错:
原因:我们数据库有一个密码,数据库表还有一个密码。
对应:我们证书库有一个密码,而每一个条目还有对应的密码。
但是tomcat配置中只有一个密码参数,所以要求证书库的密码和条目的密码需要一致。
修改对应条目的密码
第二个坑:使用keytool -help 没有-keypasswd这个参数。导致刚开始只要发现需要改条目密码就需要重新创建。=。。=很坑。
再次运行测试:
然后使用startup启动
使用浏览器访问:
浏览器导入p12文件:客户端的
安装basic.cer
----------------------------------------------2021-01-08---------更新
之前留下的坑,当时做不下去了。
最近在看http协议
里面也涉及到了https的配置。正好将这个坑给补上。
填坑了
1. 目的
首先,我们为什么需要https?
当然是安全。
http请求的报文是没有加密的,是明文的。所有的信息在互联网的世界中裸奔,谁都可以看到。
为了解决这个问题,就需要给报文加密。加密了,其他即使拦截到,也因为无法解密,从而保护报文的安全。
2. 加密
目前从秘钥的角度来说,加密分为对称加密,和非对称加密。
2.1 对称加密
给你一个数字,12345,如何进行加密呢?
比如将12345加密为34567
发现规律了吗?
我将每一位的数字都加2,这个2就是秘钥。
解密就是加密的逆过程,将每一位减2即可。
34567->12345.
这种就是对称加密:加密和解密使用相同的秘钥。
解密就是加密的逆过程。
2.2 非对称加密
还是相同的数字,12345,除了对称加密,你还能想到其他的加密方式吗?
比如将12345加密为89012
这个规律也很简单,将数字的每一位加7,然后对10进行取余。
解密和对称加密不同。
对称加密的解密是加密的逆过程。
非对称加密的加密过程中用到秘钥称为公钥。
也就是7.
根据规则和公钥,可以计算出一个私钥,这个私钥就是解密用的。
因为我们的规则是:(x+y)%10
x作为明文的位,y是公钥。
私钥的计算方式:10-y
所以,私钥是3.
非对称加密就是使用私钥,在加密一次,然后就得到明文了。
89012->12345
2.3 非对称加密的优点
使用对称加密
实际使用中,非对称加密一般更加安全。
因为对于对称加密来说,解密的人知道秘钥,就知道了加密规则。
这样就能进行伪装。
比如客户端和服务端使用对称加密。
A客户端先假装和服务器通信,获取到服务器的秘钥后,对服务器做了代理。
此时B客户端也来访问服务器,但是B客户端和服务器不知道A对服务器做了代理,此时B客户端会先访问A(代理服务器),然后A因为已经知道了对称加密的秘钥,所以A可以拦截到B的请求,然后进行解密,接着进行篡改请求,然后将篡改后的请求进行加密,接着请求服务器。
服务器收到请求,使用对称加密秘钥解密,然后响应请求,返回A。
A收到响应,将请求解密,接着篡改响应,然后将响应使用对称秘钥进行加密,返回给B。
B收到响应,解密。
举个实际的例子:
我们使用网页版的京东进行购物。
B请求给自己的手机号码充值20元。
A拦截到请求后,将请求进行篡改:给B的手机号充值20,;给A的手机号充值0.01.
京东服务器收到请求后,给A的手机号充值0.01,给B的手机充值20.
然后将服务器响应:手机号A成功充值0.01,手机号B成功充值20.
A拦截到响应,解密后,将响应修改为:手机号B成功充值20,然后加密返回。
听起来没毛病是吧。
但是整个过程中,A平白无故获得了0.01元的话费收入。
而且,现在一般充值话费,都是分为两部分:20=19.99+0.01
现在充值20元话费,运营商实际上收取19.99元。
但是在B来看,没毛病,我充值20元,花了20元。
实际上A利用信息差,从B哪里非法收入了0.01.
1个或许没问题。但是,每天通过京东充值话费的有多少呢?
使用非对称加密
在网站中,服务器一般会将公钥分发给客户端,告诉客户端,你请求我的时候,需要使用公钥加密后,在传给我。
服务端收到请求后,使用私钥进行解密,就能知道客户端的请求内容了。
非对称加密的优势在于:客户端即使获得了公钥,也无法破解私钥,无法对密文进行解密。
还是以充值话费的例子:
A假装和服务器通信,获取了公钥,然后A对服务器做了代理。
B使用相同的公钥加密请求:给B的手机号充值20元话费。
A拦截到了B的请求,因为A拿的也是公钥,无法解密,也就无法篡改了。(即使强行篡改,也会使服务器无法解密识别)
服务器最终只给B的手机号充值了20元,B只花费了19.99元。
3. tomcat https单项加密
3.1 数字证书
在互联网中,非对称加密的公钥一般存储在数字证书中。
在win系统中,使用win+r运行certmgr.msc打开证书管理界面
比如这种
证书分为很多种,有些证书中不仅仅可以有公钥,还可以有私钥
3.2 数字证书的生成
首先需要安装jdk,我们使用keytool生成数字证书。
常见来说,我们将公钥和私钥在一起存储使用keystore,也就是证书库的方式存储。
只要公钥则使用cer存储,也就是证书。
确保jdk安装成功,且版本最好和我的一致。
首先我们创建一个证书库
要求输入一些信息。
接着会生成指定的证书库
我们查看证书库
从这里看出我们真正加密算法是SHA256和RSA
3.3 tomcat配置
我们使用8.5.32版本的tomcat.
首先打开server.xml,在里面找到实例配置
将这个注释放开
然后将证书库修改为我们刚才生成的证书库。
然后启动
访问,会提示不是专用链接
点击高级,选择继续访问
最终我们可以访问到需要的界面
点击不安全几个字
会提示证书无效
查看证书,正好是我们刚才生成的
证书状态是不受信任的
4. 证书信任
我们在3中实现了tomcat下的https单项加密。
在2.3中的例子中,我们将,使用了非对称加密,可以避免信息被篡改。
但是,这不是绝对的。
我们还是以例子来说:
A假装和服务器通信,得到了服务器分发的数字证书,也就是公钥。
然后A对服务器做代理拦截。
B请求服务器充值话费,但是B不知道A做了拦截,于是B首先请求A,A发现B第一次请求,于是A将自己生成的数字证书发送给B,而B不知道自己受到的证书是A的证书,还是服务器的证书,没有验证的手段。
我们这里将服务器的证书成为真证书,而将A的证书称为野证书。
所以,B拿着A给的野证书,也就是公钥,对请求进行加密。然后将请求发送给了A。
A受到加密后的请求,用野证书的私钥进行解密,拿到了B请求的明文。然后A对请求明文进行篡改,篡改完成之后,使用服务器的真证书进行加密,加密完成后,发送隔服务器。
服务器收到加密后的密文请求,使用真证书的私钥进行解密,发现,请求符合服务器的规则,服务器能识别,于是进行了处理。
处理完成后,服务器将响应使用私钥进行加密,然后将加密后的密文响应返回给A服务器。
A服务器收到响应密文后,使用真证书的公钥进行解密(非对称加密,公钥和私钥都可以加密解密。在一次加密解密的完成过程中,必须使用两个秘钥。这两个秘钥是互补的),得到了明文响应,我们称服务器的响应为真响应,代理服务器的响应为假响应。
A服务器篡改明文真响应,然后使用自己的野证书的私钥进行加密,然后将加密后的密文假响应返回给B。
B收到A服务器的密文假响应后,使用野证书的公钥进行解密,获得了假响应的明文。
在整个通信的过程中,问题就在于B服务器无法确定自己受到的证书是真证书还是野证书,也就无法知道自己请求的是真正的服务器还是代理服务器。
4.1 http/https请求过程
看到这里可能有人会问,我们访问京东,为什么会访问到A的代理服务器呢?
这里就涉及到了http、https的请求过程了。
我们一般访问一个网站,通常有两种方式:
1.直接在浏览器的地址栏输入网站的域名进行访问。
比如常用的www.baidu.com.
一般浏览器默认是http访问,域名默认就是万维网,也就是www.
所有,有时候,在浏览器的地址栏输入baidu.com也能访问。
2.如果我们不记得网站的域名,就需要搜索,然后通过搜索结果的超链接进行访问。
不管是方法1还是方法2,本质上是相同的,都是通过域名访问网站。
我们还应该明确一点,访问网站,其实就是访问网站对应的应用。
所以,http/https请求都需要一个请求的前置操作:访问DNS。
我们在配置计算机网络的时候,要指定DNS服务器的ip地址。(有时候是DHCP则是通过IP地址的分配,计算机请求路由器,路由器返回DNS服务器地址的)
浏览器拿着域名,去问DNS,www.baidu.com的网站的IP是多少?
DNS正确的返回x.x.x.x:aaaa。
接着浏览器在去访问x.x.x.x:aaaa.
4.2 DNS劫持
如果DNS被劫持了呢?
什么是DNS劫持?
就是说我要访问百度,结果出来了百A,百B等等网站。
这就是DNS被劫持了。
DNS劫持如何实现?
如果你了解浏览器请求DNS的过程,你就很容易实现DNS劫持。
使用浏览器访问网站是一个非常频繁的操作,基本上我们使用浏览器,几乎无时无刻在访问网站,而每一次访问网站都需要请求DNS服务器。
我们每一次访问DNS服务器,就需要和DNS服务器建立TCP连接,这样整个过程是非常耗费资源的。
为了优化DNS请求的速度,我们使用多级缓存的方式,来解决这个问题。
DNS访问的优先级
- 本地hosts
- 本地DNS
- 远程DNS(远程DNS会级联上报)
- 跟域名服务器(跟DNS)
4.2.1 hosts
第一级:hosts文件。
在hosts文件中会存储一些域名和IP的映射关系。
hosts文件在C:\Windows\System32\drivers\etc
目录下
里面的内容也很简单,每一行就是一个映射关系,前面是ip地址,中间使用空格分隔,然后是域名。
比如我们增加一个DNS关系
baia.com -> baidu.com
首先我们通过cmd的ping命令得到baidu.com的ip地址
接着增加baia.com的映射
接着访问baia.com
请注意,这里访问我们劫持的baia.com必须使用https的方式请求。
因为baidu做了全站https支持。
点击高级,就会提示,我们收到的证书是baidu的证书,但是访问的域名却不是baidu的域名。
从这里也就能证明,我们确实做了dns劫持,将baia劫持到了baidu上。
不过,因为hosts文件的优先级最高,所以一般情况下,不建议修改这里的映射关系。(之前有种跳过GW的方式就是修改hosts)
因为hosts的映射失效了,就会导致域名无法访问。(但是该改还是改,不用怕,改出问题了,将自己增加的删除就行)
4.2.2 本地DNS
打开我们的服务管理
选择管理哦,不是属性。
找到DNS Clinet服务
里面的说明
DNS 客户端服务(dnscache)缓存域名系统(DNS)名称并注册该计算机的完整计算机名。如果该服务被停止,将继续解析 DNS 名称。然而,将不缓存 DNS 名称的查询结果,且不注册计算机名。如果该服务被禁用,则任何明确依赖于它的服务都将无法启动。
这个是本机的DNS,如果停止本机的DNS,那么每次就会从IP地址指定的DNS查询映射关系。
有了本机的DNS,就会将远程的DNS的映射关系,在本机进行缓存。在下一次访问的时候,就会快很多(因为本机访问,会受到网络等因素的波动影响)。
4.2.3 远程DNS
我们打开cmd,使用ipconfig/all
,查看远程DNS
这个就是我自己的远程dns,一般你在公司,使用的是公司的dns服务器,在家里,则是使用运营商的dns服务器。
在dns服务器中会对一些特殊的域名,做过滤。比如涩情、暴力、血腥的网站的域名,做个过滤,那么使用这些dns服务器的用户,就不能访问这些被过滤的网站,起到一个保护的功能。
如果远程DNS服务器上没有查询域名的映射关系,远程DNS服务器就会查询他自己的DNS服务器。也就是上报。
一直上报,直到跟域名服务器
4.2.4 跟域名服务器
根服务器主要用来管理互联网的主目录,最早是IPV4,全球只有13台(这13台IPv4根域名服务器名字分别为“A”至“M”),1个为主根服务器在美国。其余12个均为辅根服务器,其中9个在美国,欧洲2个,位于英国和瑞典,亚洲1个位于日本。
如果根域名服务器也找不到,那么很可惜,这个域名你就无法访问,其他人也无法通过域名进行访问。
4.3 根证书
对于我们京东充值话费的例子,如何避免DNS劫持下的数字证书被替换的问题呢?
其实也很简单,找一个担保人。
就像我们生活中一样,A和B借钱,但是A和B还不太熟悉,B不敢直接把钱借给A。于是A和B找了一个他们都信任,都熟悉的C,在C的担保下,B将前借给了A。
C作为担保人,就需要督促B将出借金交给A,同时在还款日期时,督促A将本金和利息归还B。
数字证书也是一样的,我们访问京东,就会收到京东的数字证书,浏览器会检查证书是否是可信的。(还记得我们3中,自己给tomcat配置单项加密的时候,证书状态是不可信的)
证书上记录了担保人,也就是颁发者。以及有效期。
同时证书的状态也是可信的。
4.3.1 创建签名证书
我们之前用借贷的方式,解释了可信证书。
在借贷场景中,我们需要找一个担保人。
同时我们在查看京东的证书的时候,我们知道了颁发者是
接着,我们打开证书管理器,在其中找找这个证书
我们发现这个证书在中间证书颁发机构的目录下。
请注意两个关键点:
- 中间机构
- 颁发机构
所以,我们看到这个中间证书的颁发者是 - 再找
- 找到了。
所以,类比这个过程,我们首先创建一个担保证书。
这个担保证书是服务器和客户端都信任的证书。
也就是签名证书。
生成一个签名证书库,
使用
查看证书库。
接着将证书库中的证书导出来(公钥)
接着我们安装签名证书(也就是公钥)
我们安装到信任的根证书办法机构目录下
我们选择是
此时在证书管理界面中就能看到我们安装的证书了
4.3.2 签名请求
现在,担保人找到了,我们需要和担保人说明白是什么事情。
比如A向担保人提出借钱请求,担保人了解情况后,就可以向其他人证明,A借钱是有能力还款的。至于谁愿意给A借,就不是担保人能决定的了。
比如你去银行借钱,找担保人担保,借1W快,担保人给你担保。
你去银行借钱,找担保人担保,借1个亿,我想,没人给你担保吧。(一个普通人的角色,大佬估计也不会看到我写的东西)
所以,首先,你要想担保人请求借钱。
这个在某些情况下,是银行要担保人出具担保证明。
然后你就带着礼物,请求担保人给你出具担保证明。
我们先生成clienta待签名的证书库
查看
此时如果我们生成clienta证书的公钥cer文件,然后安装cer公钥文件,会不受信任的。
对于clienta生成签名请求
查看签名请求
4.3.3 签名回复
借款人找到担保人说明请求后,担保人经过评估,同意开具担保证明。也就是同意在担保证明上签字。或者叫回复。
所以,我们使用信任的basic证书库对clienta_req.cer的签名请求进行回复。(也可以认为是签名过程)
查看签名回复
怎么说呢,这个结合我们的例子,主要就是这样的。
服务器直接将自己的证书进行分发,容易出现被篡改。
所以。服务器分发的是经过担保机构加密的证书。
此时即使别人拦截了加密的证书,对证书进行替换,也无法通过担保机构的审核(因为审核需要备案,像一个域名,基本上只允许注册一个证书(同一个担保机构)),如果代理服务器想替换证书,就意味着一个域名有两个证书,这样就有问题了。
就会出现我们在4.2.1中的,劫持了百度的dns,然后就无法访问,因为证书和域名不匹配。
这样就在一定程度上避免了篡改和替换。
4.3.4 签名回复导入
在上面我们讲到,签名过程实际上是将clienta的公钥使用信任证书basic的私钥进行加密,然后返回clienta加密后的密文。
然后clienta的证书库就会将信任证书basic加密后的密文倒入自己的证书库。
要让整个信任链能成功建立,首先cliena证书库要先信任basic才行,我只有先信任你,才能信任你的签名。
先让clienta证书库导入信任证书库的公钥
此时查看clienta证书库
虽然别名相同,但是类型不同哦。
然后将签名回复导入
因为我们已经信任了basic,所以,basic的回复,直接就会信任,并不会在给出提示,询问是否信任。
我们查看clienta证书库
接着导出clienta证书库的公钥证书
此时查看
发现证书链的长度已经变成了2,证书1是clienta的证书,证书2就是信任证书basic的公钥
请注意证书2的指纹尾数是88
而clienta证书中信任basic的证书的指纹尾数也是88
将接受了签名回复的证书库导出证书(公钥)
然后安装证书
此时,颁发者就是信任证书了。
证书的状态和证书链也都是完整的。
5. tomcat https加密(证书安全)
我们在4中生成了安全的,经过信任的证书。
接着我们将信任的证书库,配置到tomcat中。
然后重启tomcat,然后访问
虽然还是报红(这是没办法的,我们的根证书basic是野证书,真正的ca证书签名要花钱的)
但是,当我们查看证书的时候,证书是有效的。
还有一点,请注意,我们给tomcat配置了证书库和密码,tomcat生成了只有90天的证书,然后将这个证书分发给了浏览器。
keytool导出证书,有效期无法修改,只能是90天。
如果有浏览器和tomcat中间有代理服务器,拦截了tomcat分发的证书,那么,只要我们没有用basic对代理服务器的证书进行签名,那么这里证书就是有问题的(类似之前看到的baia和百度的证书)
6. tomcat https双向加密(证书安全)
因为既有服务器端证书,也有客户端证书。
所以,我们先卸载全部的自己安装的证书,留下信任证书basic.
然后删除目前我们生成的clienta的证书。(不删除也行,重新生成也行)
这部分就和原来写的6完全相同了。(只操作6就行了,不需要8)
这里不再重新赘述。
你生成的证书应该有这些:
然后我们打开tomcat的server.xml,进行配置
可以在tomcat的webapps目录下的doc目录下,查看tomcat的文档
找到ssl相关的html
浏览器中会展示这样的
找到Connector
找到SSLHostConfig
然后就能找到配置项和说明了
这里需要注意protocol的版本哦
接着我们启动tomcat,然后用浏览器访问
会提示没有提供登录证书
可以看到,服务器端的证书是有了,但是客户端的证书还没有
我们使用keytool将keystore转为p12类型的证书。
用于安装
此时生成了clienta.p12的安装证书库。
我们双击安装
自动选择证书存储位置就行
接着刷新浏览器,浏览器就会提示我们选择用于身份验证的证书
我们点击确定,就可以访问了
注意点:细心。双向认证,我从头开始做了不下8遍。不细心,导致各种各样的问题。特别是协议不支持的问题。
7. tomcat https 双向加密-多证书(证书安全)
前面将的都是配置一个客户端证书,一个服务端证书。
如果我们有多组证书该怎么配置呢?
先要明白,一个端口确实只能配置一对证书。
但是我们可以做端口转发。
比如我按照7中的例子,生成了clientb的证书。以及serverb的证书。
接着我们在tomcat的server.xml中配置
里面主要注意两个点:首先是端口不能存在冲突,其次是做端口转发。
接着启动,并访问8442端口
此时客户端的证书都是安装的
客户端认证证书,需要带有私钥的
我们删除clienta证书,此时8443无法访问。
右键删除就行
重启浏览器此时访问8443
会要我们选择一个证书。
也就是说,只要客户端有任意一个证书就行,不管是哪个端口。如果我们将clienta证书也安装。重启浏览器访问
此时选择证书就是两个
注意点:浏览器每次重启,都需要选择客户端认证的证书。
所以,如果修改了tomcat配置,发现证书还是生效。那么可能需要重启浏览器。
如果是安装证书,则不需要重启浏览器。
至此,终于将这个大坑填上。