乐趣区

使用tomcat搭建https服务

DevUI 是一支兼具设计视角和工程视角的团队,服务于华为云 DevCloud 平台和华为内部数个中后台系统,服务于设计师和前端工程师。
官方网站:devui.design
Ng 组件库:ng-devui(欢迎 Star)
官方交流群:添加 DevUI 小助手(微信号:devui-official)进群

引言

本文主要讲述如何使用 tomcat 搭建 https 服务,主要内容有:

1 https 协议基础和数字证书基础

2 基础环境准备

3 使用自签名证书配置 tomcat

4 模拟使用 CA 认证的证书配置 tomcat 单向认证

5 配置 tomcat 双向认证

1 https 协议基础和数字证书基础

https 协议

参考维基百科定义:超文本传输安全协议(英语:HyperText Transfer Protocol Secure,缩写:HTTPS;常称为 HTTP over TLS、HTTP over SSL 或 HTTP Secure)是一种通过计算机网络进行安全通信的传输协议。HTTPS 经由 HTTP 进行通信,但利用 SSL/TLS 来加密数据包。HTTPS 开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。这个协议由网景公司(Netscape)在 1994 年首次提出,随后扩展到互联网上。

历史上,HTTPS 连接经常用于万维网上的交易支付和企业信息系统中敏感信息的传输。在 2000 年代末至 2010 年代初,HTTPS 开始广泛使用,以确保各类型的网页真实,保护账户和保持用户通信,身份和网络浏览的私密性。

关键点:http 协议本身不安全,https 是在 http 协议基础上,增加一个 SSL 的传输层,用于保证 http 协议的安全

HTTPS = HTTP + SSL

数字证书

这里讲解一些基本概念:

公开密钥密码学 / 非对称式密码学

公开密钥密码学(英语:Public-key cryptography)也称非对称式密码学(英语:Asymmetric cryptography)是密码学的一种算法,它需要两个密钥,一个是公开密钥,另一个是私有密钥;公钥用作加密,私钥则用作解密。使用公钥把明文加密后所得的密文,只能用相对应的私钥才能解密并得到原本的明文,最初用来加密的公钥不能用作解密。由于加密和解密需要两个不同的密钥,故被称为非对称加密;不同于加密和解密都使用同一个密钥的对称加密。公钥可以公开,可任意向外发布;私钥不可以公开,必须由用户自行严格秘密保管,绝不透过任何途径向任何人提供,也不会透露给被信任的要通信的另一方。

关键点:用公钥加密,用私钥解密

上图来自《图解密码技术》一书

数字签名

数字签名(英语:Digital Signature,又称公钥数字签名)是一种功能类似写在纸上的普通签名、但是使用了公钥加密领域的技术,以用于鉴别数字信息的方法。一套数字签名通常会定义两种互补的运算,一个用于签名,另一个用于验证。法律用语中的电子签章与数字签名代表之意义并不相同。电子签章指的是依附于电子文件并与其相关连,用以辨识及确认电子文件签署人身份、资格及电子文件真伪者;数字签名则是以数学算法或其他方式运算对其加密而形成的电子签章。意即并非所有的电子签章都是数字签名。

数字签名不是指将签名扫描成数字图像,或者用触摸板获取的签名,更不是落款。

数字签名了的文件的完整性是很容易验证的(不需要骑缝章、骑缝签名,也不需要笔迹鉴定),而且数字签名具有不可抵赖性(即不可否认性),不需要笔迹专家来验证

关键点:

1 用私钥加密来生成签名,用公钥解密来验证签名

2 使用数字签名可以识别篡改和伪装,防止否认

上图来自《图解密码技术》一书

数字证书

公开密钥认证(英语:Public key certificate),又称数字证书(digital certificate)或身份证书(identity certificate)。是用于公开密钥基础建设的电子文件,用来证明公开密钥拥有者的身份。此文件包含了公钥信息、拥有者身份信息(主体)、以及数字证书认证机构(发行者)对这份文件的数字签名,以保证这个文件的整体内容正确无误。拥有者凭着此文件,可向电脑系统或其他用户表明身份,从而对方获得信任并授权访问或使用某些敏感的电脑服务。电脑系统或其他用户可以透过一定的程序核实证书上的内容,包括证书有否过期、数字签名是否有效,如果你信任签发的机构,就可以信任证书上的密钥,凭公钥加密与拥有者进行可靠的通信。

简而言之,认证机构用自己的私钥对需要认证的人(或组织机构)的公钥施加数字签名并生成证书,即证书的本质就是对公钥施加数字签名。

数字证书的其中一个最主要好处是在认证拥有者身份期间,拥有者的敏感个人数据(如出生日期、身份证号码等)并不会传输至索取数据者的电脑系统上。透过这种数据交换模式,拥有者既可证实自己的身份,亦不用过度披露个人数据,对保障电脑服务访问双方皆有好处。

X.509 证书

X.509 是数字证书的一个标准结构,

一般遵从 X.509 格式规范的证书,会有以下的内容,它们以字段的方式表示 [12]:

版本:现行通用版本是 V3
序号:用以识别每一张证书,特别在撤消证书的时候有用
主体:拥有此证书的法人或自然人身份或机器,包括:
国家(C,Country)
州 / 省(S,State)
地域 / 城市(L,Location)
组织 / 单位(O,Organization)
通用名称(CN,Common Name):在 TLS 应用上,此字段一般是网域
发行者:以数字签名形式签署此证书的数字证书认证机构
有效期开始时间:此证书的有效开始时间,在此前该证书并未生效
有效期结束时间:此证书的有效结束时间,在此后该证书作废
公开密钥用途:指定证书上公钥的用途,例如数字签名、服务器验证、客户端验证等
公开密钥
公开密钥指纹
数字签名
主体别名:例如一个网站可能会有多个网域(www.wikipedia.org, zh.wikipedia.org, zh.m.wikipedia.org 都是维基百科)、一个组织可能会有多个网站(*.wikipedia.org, *.wikibooks.org, *.wikidata.org 都是维基媒体基金会旗下的网域),不同的网域可以一并使用同一张证书,方便实现应用及管理

例如维基百科证书

2 基础环境

基础环境:JDK8 + tomcat7

Jdk 官网下载 https://www.oracle.com/java/technologies/javase-jdk8-downloads.html

tomcat 官网下载 https://tomcat.apache.org/

具体安装这里不赘述

3 tomcat 配置自签名证书

步骤 1 生成证书

生成服务端密钥对

生成一个包含证书的密钥库文件,服务器可以使用该证书

简化 cmd 命令:

keytool -genkey -alias tomcat -keysize 2048 -validity 3650 -keyalg RSA -keystore tomcat.jks

命令说明 (keytool -genkey –help):

-genkey 表示生成密钥对

-alias <alias> 要处理的条目的别名

-keyalg <keyalg> 密钥算法名称, 应该优先选择 RSA 算法作为安全算法,这还可以确保与其他服务器和组件的一般兼容性

-keysize <keysize> 密钥位大小

-validity <valDays> 有效天数

手动输入参数说明:

CN(您的名字与姓氏是什么?)申请证书的域名

OU(您的组织名称是什么?)申请单位的所在部门名称

O(您所在的城市或区域名称是什么?)申请单位的所在公司名称

L(您所在的省 / 市 / 自治区名称是什么?)申请单位的所在城市

ST(您所在的省 / 市 / 自治区名称是什么?)申请单位的所在省份

C(该单位的双字母国家 / 地区代码是什么?)申请单位所属国家,ISO 国家代码(两位字符)

其他说明:密钥库口令和密钥口令为了简单,设置为同一个默认密码 changeit

也可以使用完整命令一次生成证书:

keytool -genkey -alias tomcat -keystore tomcat.jks -keypass changeit -storepass changeit -keyalg RSA -keysize 2048 -validity 365 -v -dname "CN = YWJ,OU = DevUI,O = DevCloud,L = ShenZhen,ST = GUANGDONG,C = CN"

查看证书

证书生成后,使用如下命令查看证书内容

keytool -list -v -keystore tomcat.jks

如果一切成功,那么您现在将拥有一个包含证书的密钥库文件,服务器可以使用该证书

步骤 2 配置 tomcat

修改 %TOMCAT_HOME%/conf/server.xml

<!-- 自生成证书 -->

<Connector
  protocol="org.apache.coyote.http11.Http11NioProtocol"
  port="443" maxThreads="200"
  scheme="https" secure="true" SSLEnabled="true"
  keystoreFile="keystore\_guanwang/tomcat.jks"
  keystorePass="changeit"
  clientAuth="false" sslProtocol="TLS"
/>

4 模拟正式 CA 认证的证书配置 tomcat 单向认证

具备阶段

申请正式证书流程

首先,我们先生成如下证书文件

1 DevUI 自身密钥库文件:devui.jks

keytool -genkey -alias devui -keystore devui.jks -keypass changeit -storepass changeit -keyalg RSA -keysize 2048 -validity 3650 -v -dname "CN = YWJ,OU = DevUI,O = DevCloud,L = ShenZhen,ST = GUANGDONG,C = CN"

2 CA 机构的密钥库文件:ca.jks (CA 密钥对都是模拟的)

keytool -genkey -alias ca -keystore ca.jks -keypass changeit -storepass changeit -keyalg RSA -keysize 2048 -validity 3650 -v -dname "CN = myca,OU = CA,O = CA,L = BEIJING,ST = BEIJING,C = CN"

接下来我们以 DevUI 这个组织机构为例,向 CA 机构申请签名证书

1)DevUI 使用 certreq 生成一个证书签名请求文件 devui_to_ca.csr

2)CA(证书认证中心)使用 gencert 生成证书 ca_to_devui.cer

3)DevUI 收到 CA 证书后,使用 importcert 将证书导入到自身的 devui.jks

步骤 1 DevUI 使用 certreq 生成一个证书签名请求文件

DevUI 使用自身的 jks 密钥生成一个证书签名请求

cmd 命令:

keytool -certreq -alias devui -keystore devui.jks -file devui\_to\_ca.csr -v

参数说明:

-certreq 表示证书签名请求

-keystore <keystore> 密钥库名称

-alias <alias> 要处理的条目的别名

-file <filename> 输出文件名

-v 详细输出

这里创建的证书请求文件 devui_to_ca.csr。将此文件提交到 CA,例如 VeriSign 等。CA 对请求者进行身份验证(通常是脱机),并返回由他们签名的证书,以对 DevUI 的公钥进行身份验证。

步骤 2 CA(证书认证中心)使用 gencert 签发证书

Cmd 命令:

keytool -gencert -alias ca -infile devui_to_ca.csr -outfile ca_to_devui.cer -keystore ca.jks

参数说明:

-alias <alias> 要处理的条目的别名

-keystore <keystore> 密钥库名称

-infile <filename> 输入文件名

-outfile <filename> 输出文件名

备注: 这里模拟了 CA(证书认证中心)根据 csr 文件生成证书的过程,真实情况下要向真实的 CA 例如 VeriSign 等,提交申请

步骤 3 DevUI 收到 CA 证书后,使用 importcert 将证书导入到自身的 keystore 中

Cmd 命令:

keytool -importcert -file ca\_to\_devui.cer -keystore devui.jks -alias devui

这里出现错误,无法从回复中建立链:

keytool 错误: java.lang.Exception: 无法从回复中建立链

问题原因:ca.jks 的证书时会对其签名做验证,需要确认是由信任机构 CA 颁发的。当前服务端当前并未将模拟 CA 的证书导入到的本机的信任证书列表中,导致抛出该错误

解决方案: 首先从 ca.jks 导出 CA 机构的公钥证书 ca.cer,然后将 ca.cer 导入 devui.jks 中。

1)从 ca.jks 导出 CA 机构的公钥证书 ca.cer

Cmd 命令:

keytool -exportcert -alias ca -file ca.cer -keystore ca.jks

2)将 ca.cer 导入 devui.jks 中

Cmd 命令

keytool -importcert -alias ca -keystore devui.jks -file ca.cer -storepass changeit

默认密码也是 changeit

3)通过证书查看命令可以看到包含两个证书的证书链

keytool -list -v -keystore devui.jks

步骤 4 配置 tomcat 单向认证

<Connector
  protocol="org.apache.coyote.http11.Http11NioProtocol"
  port="443" maxThreads="200"
  scheme="https" secure="true" SSLEnabled="true"
  keystoreFile="keystore\_guanwang/devui.jks"
  keystorePass="changeit"
  clientAuth="false"
  sslProtocol="TLSv1.2"
/>

5 tomcat 配置双向认证

Tomcat 双向认证只需要在上面单向认证的基础上,增加如下步骤:

1 新增客户端认证文件 client.jks

2 将 ca_to_devui.cer 导入到 client.jks 中

3 配置 tomcat 双向认证

步骤 1 新增客户端认证文件

Cmd 命令:

keytool -genkey -alias client -keystore client.jks -keypass changeit -storepass changeit -keyalg RSA -keysize 2048 -validity 3650 -v -dname "CN = client,OU = DevUIClient,O = DevCloud,L = ShenZhen,ST = GUANGDONG,C = CN"

步骤 2 将 ca.cer 导入到 client.jks 中

Cmd 命令

keytool -importcert -alias ca -keystore client.jks -file ca\_to\_devui.cer -storepass changeit

步骤 3 配置 tomcat 双向认证

<Connector
  protocol="org.apache.coyote.http11.Http11NioProtocol"
  port="443"
  maxThreads="200"
  scheme="https" 
  secure="true" 
  SSLEnabled="true"
  keystoreFile="keystore\_guanwang/devui.jks"
  keystorePass="changeit"

  truststoreFile="keystore\_guanwang/client.jks"
  truststorePass="changeit"
  clientAuth="ture"

  sslProtocol="TLS"
/>

附录参考

https 协议 RFC:https://tools.ietf.org/html/rfc2818

维基百科:

HTTPS: https://zh.wikipedia.org/zh-cn/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%AE%89%E5%85%A8%E5%8D%8F%E8%AE%AE

公开密钥加密(非对称加密):https://zh.wikipedia.org/wiki/%E5%85%AC%E5%BC%80%E5%AF%86%E9%92%A5%E5%8A%A0%E5%AF%86

数字签名:

https://zh.wikipedia.org/wiki/%E6%95%B8%E4%BD%8D%E7%B0%BD%E7%AB%A0

数字证书:

https://zh.wikipedia.org/zh-cn/%E5%85%AC%E9%96%8B%E9%87%91%E9%91%B0%E8%AA%8D%E8%AD%89

X.509 证书:

https://zh.wikipedia.org/zh-cn/X.509

keytool 官方说明:

https://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html

httpclient4.5 官方网站

https://hc.apache.org/httpcomponents-client-4.5.x/quickstart.html

httpclient 客户端代码 demo:

https://hc.apache.org/httpcomponents-client-4.5.x/httpclient/examples/org/apache/http/examples/client/ClientCustomSSL.java

https 协议简要说明和数字签名可以参考如下文章:

https://zhuanlan.zhihu.com/p/57142784

https://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html

华为云证书申请流程

https://support.huaweicloud.com/qs-scm/scm_07_0001.html

参考书籍

《Java 加密与解密的艺术》

《图解 HTTP》

《图解密码技术》

加入我们

我们是 DevUI 团队,欢迎来这里和我们一起打造优雅高效的人机设计 / 研发体系。招聘邮箱:muyang2@huawei.com。

文 /DevUI 杰哥

往期文章推荐

《关于 Git rebase 你必须要知道的几件事》

《Web 界面深色模式和主题化开发》

《手把手教你搭建一个灰度发布环境》

退出移动版