欢迎使用普元产品知识库,本知识库包含普元应用开发平台EOSPlatform,流程平台BPS,企业服务总线ESB,微服务平台Microservice,运维管理平台Devops,数据集成平台DI

页面树结构

欢迎使用普元文档库

Skip to end of metadata
Go to start of metadata


HTTPS双向认证原理

双向认证是指客户端和服务器端都需要验证对方的身份。单向认证的过程是客户端从服务器端下载服务器端公钥证书进行验证,然后建立安全通信通道。与单向认证不同的是,双向认证过程中,客户端除了需要从服务器端下载服务器的公钥证书进行验证外,还需要把客户端的公钥证书上传到服务器端给服务器端进行验证,等双方都认证通过了,才开始建立安全通信通道进行数据传输。

整个过程参考下图:


应用服务器的密钥库和证书库

在应用服务器中,有两个比较重要的文件:keystore.jks和cacerts.jks,其中keystore.jks是应用服务器的密钥库文件,cacerts.jks是应用服务器的证书库文件。应用服务器配置文件domain.xml中相关配置如下:

<jvm-options>-Djavax.net.ssl.keyStore=${com.sun.aas.instanceRoot}/config/keystore.jks</jvm-options>
<jvm-options>-Djavax.net.ssl.trustStore=${com.sun.aas.instanceRoot}/config/cacerts.jks</jvm-options>

默认情况下,应用服务器支持HTTPS的单向认证,应用程序部署后就可以使用HTTPS方式进行访问,无需任何配置。要支持HTTPS的双向认证,则需要保证服务端和客户端可以互相验证。


证书准备和配置

我们需要准备如下证书及密钥库文件:

文件

说明

root.jks

根证书密钥库

root.cer

根证书,用于认证客户端证书及安装到客户端

keystore.jks

服务端密钥库

s1as.cer

服务端证书,使用根证书root.cer认证后的证书

pas-instance.cer

应用服务器证书,用于服务器自己的HTTPS认证

client.p12

客户端密钥库

client.cer

客户端证书

其中,根证书root.cer、服务端证书s1as.cer、应用服务器证书pas-instance.cer需要导入到keystore.jk保证应用服务器信任这些证书;根证书root.cer、服务端证书s1as.cer、客户端证书client.cer需要导入到cacerts.jks用于客户端和服务端互相认证。另外,根证书root.cer、客户端密钥库需要安装到客户端(如浏览器端,不同系统的安装方式可能不同)。

生成根证书

生成根证书密钥库root.jks,(进入%JAVA_HOME%/bin执行以下命令,后面生成其他证书命令执行同样在该路径下):

keytool -genkeypair -v -keystore root.jks -storetype pkcs12 -storepass changeit -alias root -keyalg RSA -keysize 2048 -validity 3650 -dname "CN=localhost-instance,OU=PAS,O=Primeton,L=Shanghai,ST=Shanghai,C=CN"

导出根证书root.cer

keytool -exportcert -file root.cer -keystore root.jks -storepass changeit -alias root

生成服务端证书

生成应用服务器密钥库keystore.jks

keytool -genkeypair -v -keystore keystore.jks -storetype pkcs12 -storepass changeit -alias s1as -keyalg RSA -keysize 2048 -validity 3650 -dname "CN=localhost-instance,OU=PAS,O=Primeton,L=Shanghai,ST=Shanghai,C=CN"

生成服务端证书请求s1as.csr

keytool -certreq -keystore keystore.jks -storepass changeit -alias s1as -file s1as.csr

使用根证书认证生成服务器证书s1as.cer

keytool -gencert -v -infile s1as.csr -outfile s1as.cer -keystore root.jks -storepass changeit -alias root

根证书导入应用服务器密钥库keystore.jks

keytool -importcert -file root.cer -keystore keystore.jks -storepass changeit -alias root

服务端证书s1as.cer重新导入服务器密钥库keystore.jks

keytool -importcert -file s1as.cer -keystore keystore.jks -storepass changeit -alias s1as

根证书导入应用服务器证书库cacerts.jks

keytool --importcert -v -trustcacerts -keystore cacerts.jks -alias root -file root.cer -keypass changeit -storepass changeit

服务端证书s1as.cer导入应用服务器证书库cacerts.jks

keytool --importcert -v -trustcacerts -keystore cacerts.jks -alias s1as -file s1as.cer -keypass changeit -storepass changeit

生成应用服务器证书

生成pas-instance密钥库keystore.jks

keytool -genkeypair -v -keystore keystore.jks -storetype pkcs12 -storepass changeit -alias pas-instance -keyalg RSA -keysize 2048 -validity 3650 -dname "CN=localhost-instance,OU=PAS,O=Primeton,L=Shanghai,ST=Shanghai,C=CN"

导出pas-instance证书pas-instance.cer

keytool -export -keystore keystore.jks -alias pas-instance -file pas-instance.cer -storepass changeit

导入pas-instance证书到cacerts.jks

keytool --importcert -v -trustcacerts -keystore cacerts.jks -alias pas-instance -file pas-instance.cer -keypass changeit -storepass changeit

生成客户端证书

生成客户端密钥库client.p12

keytool -genkeypair -v -keystore client.p12 -storetype pkcs12 -storepass changeit -alias client -keyalg RSA -keysize 2048 -validity 3650 -dname "CN=localhost-instance,OU=PAS,O=Primeton,L=Shanghai,ST=Shanghai,C=CN"

导出客户端证书client.cer

keytool -exportcert -v -file client.cer -keystore client.p12 -storepass changeit -alias client

客户端证书client.cer导入应用服务器证书库cacerts.jks

keytool --importcert -v -trustcacerts -keystore cacerts.jks -alias client -file client.cer -keypass changeit -storepass changeit


应用服务器配置

替换密钥库和证书库

将密钥库文件keystore.jks和证书库文件cacerts.jks拷贝到$APPSERVER_HOME/pas/domain/domain1/config目录下,覆盖同名文件。

⚠️注意:建议覆盖前提前做好文件备份。

开启客户端验证

访问应用服务器控制台,进入[配置/server-config/HTTP服务/HTTP监听程序]菜单页面,点击http-listener-2连接进入配置界面。

 

http-listener-2的[SSL]TAB页中,勾选客户机验证复选框,点击<保存>按钮。

 

重启应用服务器

以上配置完成之后,重启应用服务器使配置生效。

验证

使用浏览器验证

安装根证书root.cer

鼠标双击root.cer安装根证书(不同系统的安装方式可能不同)。

安装客户端密钥库client.p12

鼠标双击client.p12安装客户端密钥库(不同系统的安装方式可能不同)。

浏览器端验证

这里已经在应用服务器上部署了测试应用“certificate”,如下图:

 

点击“访问”,出现url列表,选择HTTPS方式访问,浏览器会提示选择证书。选择已安装的客户端证书即可以HTTPS方式访问应用程序。

 

⚠️注意:如果没有安装客户端密钥库,浏览器不会弹出选择证书的提示。

选择证书后,可以正常访问应用程序页面。

 

使用curl验证

使用curl方式验证HTTPS的双向认证,需要使用client.key和client.cer,因此需要生成这两个文件。

生成client.key

openssl pkcs12 -nocerts -in client.p12 -out client.key

生成client.pem

openssl pkcs12 -clcerts -nokeys -in client.p12 -out client.pem

验证

curl --cert ./client.pem --key ./client.key https://localhost:8181/certificate/ -k -v
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8181 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
Enter PEM pass phrase:
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=CN; ST=Shanghai; L=Shanghai; O=Primeton; OU=PAS; CN=localhost-instance
*  start date: Nov 18 09:32:12 2021 GMT
*  expire date: Feb 16 09:32:12 2022 GMT
*  issuer: C=CN; ST=Shanghai; L=Shanghai; O=Primeton; OU=PAS; CN=localhost-instance
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7ff74a010a00)
> GET /certificate/ HTTP/2
> Host: localhost:8181
> User-Agent: curl/7.64.1
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 4294967295)!
< HTTP/2 200
< x-powered-by: JSP/2.3
< set-cookie: JSESSIONID=6ddef088400e54c642a4f7216fb6; Path=/certificate; Secure; HttpOnly
< content-type: text/html;charset=UTF-8
<
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
* Connection #0 to host localhost left intact
* Closing connection 0

⚠️注意:因为在生成客户端密钥库的时候,设置了密码,在执行命令的时候会要求输入密码:Enter PEM pass phrase,这时输入正确的密码即可。