易语言服务端与客户端怎么传送_如何在Tomcat中做TLS客户端认证

常见的https网站做的是服务端认证(server authentication),浏览器通过证书判断你所访问的https://baidu.com是否真的是百度,而不是其他人伪造的网站。同时还对流量加密,防止别人窃听你的流量。

tls还可以做客户端认证(client authentication),即服务端判断客户端是否为其所信任的客户端。由此可见,客户端认证用于那些需要受控访问服务端。

在数据中心中,有些服务是非常敏感的,那么我们要做到:

  1. 客户端和我的流量是加密的,防止别人监听
  2. 客户端能够确认所访问的服务端的确是我们提供的服务端,而不是别人伪造的服务端
  3. 只有我信任的客户端可以访问我,防止恶意请求

所以很明显,前两个问题可以通过服务端认证解决,最后一个问题可以通过客户端认证解决。顺便一提,如果要使用客户端认证就必须使用服务端认证。

先来讲讲概念然后举个tomcat的例子讲讲怎么做。

概念

服务端认证

不论是做Server authentication还是Client authentication都需要证书。证书的来源有两种:

  • 由权威CA签发,一般都是去购买。也可以使用let's encrypt申请免费证书。
  • 自己签发

在一切可能的情况下都应该使用权威CA签发的证书,为什么这么建议?因为这里牵涉到一个信任问题,浏览器、编程语言SDK和某些工具都维护了一个信任CA证书清单,只要是由这些CA签发的证书那就信任,否则就不信任。而这个链条是可以多级的,这里就不展开了。你只需要知道由信任CA签发的所有证书都是可信的。比如JDK自带的信任CA证书可以通过下面命令看到:

keytool -list -keystore $JAVA_HOME/jre/lib/security/cacertsverisignclass2g2ca [jdk], 2016-8-25, trustedCertEntry,证书指纹 (SHA1): B3:EA:C4:47:76:C9:C8:1C:EA:F2:9D:95:B6:CC:A0:08:1B:67:EC:9Ddigicertassuredidg3 [jdk], 2016-8-25, trustedCertEntry,证书指纹 (SHA1): F5:17:A2:4F:9A:48:C6:C9:F8:A2:00:26:9F:DC:0F:48:2C:AB:30:89verisignuniversalrootca [jdk], 2016-8-25, trustedCertEntry,...

让你输密码的时候输入changeit。

如果这个证书不是由信任CA签发的(比如自己签发)会发生什么?浏览器、编程语言SDK、你所使用的工具会报告以下错误:

curl:

curl: (60) SSL certificate problem: self signed certificate in certificate chain

Java:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1964) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:328) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:322) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1614)...

浏览器:

0db4cab21fc5a8b87f6e50ee25a1d05e.png

这个错误实际上就是在告诉你这个证书不可信任,可能是一个伪造站点,让你小心点儿。如果这个证书由权威CA签发,那么就没有这个问题了。但是权威CA签发的证书要求申请人拥有域名,如果你这个服务是内部使用的没有域名,那就只能自己签发了。那么如何解决上面的问题呢?你得把自己签发的证书加入到信任CA证书清单里。

下图是权威CA签发证书的示例:

389b0acdc89217824affa65b006bb1a2.png

可以看到客户端有一个truststore,这个就是存放信任CA证书的地方,服务端有一个keystore,存放的自己的证书及对应的私钥。

下图是自签发证书的示例:

2af3d806e8a8018f8622c2cb60cd1326.png

在上面可以看到我们自己成为了一个Root CA,把它放到客户端的truststore里。

客户端认证

前面讲过客户端认证是服务端来验证客户端是否可信的机制,其实做法和服务端认证类似只不过方向相反。客户端认证大多数情况下只能是自签发的(因为没有域名),虽然不是不可以从权威CA签发但是存在一些问题。下面解释为什么,假设权威CA是let's encrypt,然后服务端信任它签发的所有证书。但是let's encrypt是阿猫阿狗都可以申请的,现在有一个黑客申请了这个证书,然后请求你的服务端,服务端就认可了。

上面这个问题可以用这个方法解决:比如你用let's encrypt申请了A证书,黑客用let's encrypt申请了B证书,你的服务端的truststore只信任A证书,那么黑客用B证书访问你的时候就会被拒绝。但是这就带来另一个问题,比如你在开发的时候客户端证书有这么几套:生产用、调试用、开发用,那么每次客户端签发一个证书都要更新到你的服务器的truststore里,这也太麻烦了。

所以结合安全性和便利性,我们把自己变成Root CA,然后服务端信任它,这样一来服务端就可以在开发的时候把Client Root CA内置进去,大大减轻了维护truststore的工作量,看下图:

673c076bef65df4c2ca65fbc76d32140.png

用Tomcat举个例子

下面举一个Tomcat做客户端认证的例子,因为是测试用,所以服务端认证也是用的自签发证书。

我们用了cfssl这个工具来生成证书。

服务端

先弄一套目录:

# 放自签发的服务端CA根证书server-secrets/ca# 放自签发的服务端的证书server-secrets/cert# 放服务端的keystore和truststoreserver-secrets/jks

生成自签名CA证书

新建文件:server-secrets/ca/server-root-ca-csr.json

内容如下:

{ "key": { "algo": "rsa
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值