前言
这个方案的很多核心问题都是在公司同事 的帮助下解决的,本文特别予以感谢。本文是通过自签名证书对GeoSmarter5.2系统进行https改造,为了使得改造成本变低本文采用把tomcat使用https + nginx使用https的方式(如果仅修改nginx的话,会需要修改程序jsp获取scheme的逻辑,否则将获取不到css和js)。
nginx:
使用我的脚本自签名证书给nginx签发一对tls证书,脚本如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/bin/sh
HOST = $1
PASSWORD = "123@Abc.com"
SUBJECT = "/C=CN/ST=Hubei/L=Wuhan/O=GeoStar/CN= $HOST "
# create self-signed server certificate:
echo "Create server key..."
openssl genrsa -passout pass:$PASSWORD -des3 -out $HOST .key 4096
echo "Create server certificate signing request..."
openssl req -passin pass:$PASSWORD -new -subj $SUBJECT -key $HOST .key -out $HOST .csr
echo "Remove password..."
mv $HOST .key $HOST .origin.key
openssl rsa -passin pass:$PASSWORD -in $HOST .origin.key -out $HOST .key
echo "Sign SSL certificate..."
openssl x509 -req -passin pass:$PASSWORD -days 3650 -in $HOST .csr -signkey $HOST .key -out $HOST .crt
echo "Example TODO:"
echo "Copy $HOST .crt to /etc/nginx/ssl/ $HOST .crt"
echo "Copy $HOST .key to /etc/nginx/ssl/ $HOST .key"
echo "Add configuration in nginx:"
echo "server {"
echo " ..."
echo " listen 443 ssl;"
echo " ssl_certificate /etc/nginx/ssl/ $HOST .crt;"
echo " ssl_certificate_key /etc/nginx/ssl/ $HOST .key;"
echo "}"
Copy 执行脚本的时候,脚本的第一个参数是nginx的ip,这个很关键,因为程序在调用https的接口的时候回校验证书,如果你的host跟证书的CommonName不匹配的话就会报错:
1
2
3
4
5
javax.net.ssl.SSLPeerUnverifiedException: Certificate for <xxx> doesn't match common name of the certificate subject: xx.xxx.xx.xx
at org.apache.http.conn.ssl.DefaultHostnameVerifier.matchCN(DefaultHostnameVerifier.java:186)
at org.apache.http.conn.ssl.DefaultHostnameVerifier.verify(DefaultHostnameVerifier.java:133)
at org.apache.http.conn.ssl.DefaultHostnameVerifier.verify(DefaultHostnameVerifier.java:99)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.verifyHostname(SSLConnectionSocketFactory.java:463)
Copy 生成证书以后,拷贝证书到应用代理的nginx容器,把证书配置到应用代理的nginx配置中:
1
2
3
4
5
6
server{
listen 9010 ssl ;
ssl_certificate <crt公钥证书> ;
ssl_certificate_key <key私钥证书> ;
error_page 497 307 https:// $host:$server_port$request_uri ;
}
Copy 然后修改location下的proxy_pass地址为https协议,一般cas我们是不需要修改的,修改其他应用即可。
其他应用(tomcat下):
①屏蔽系统配置初始化的选项,这个配置在/srv/tomcat8/bin/catalina.sh,打开脚本后一般在第一或者第二页能够找到形如:
1
java - jar / opt / jar / update - bigdatacenter - config . jar ***
Copy 在这一句前面添加一个#号,注释掉。
②给tomcat生成一个keystore证书:
1
2
$ mkdir /ssl
$ keytool -genkey -alias tomcat -keyalg RSA -storetype pkcs12 -validity 7300 -keystore /ssl/server.keystore -keysize 2048 -keypass DwpPAd23xzvZTn09RmMuZKe3T4FeXfhM -storepass DwpPAd23xzvZTn09RmMuZKe3T4FeXfhM -dname "CN=GeoStar, OU=GeoStar, O=GeoStar, L=Wuhan, S=Hubei, C=China"
Copy ③配置证书到8080端口,有人会疑问为啥不直接用8443端口,很简单,为了不用改动容器的端口映射:
1
2
3
4
5
6
7
8
9
10
11
<!-- # 屏蔽掉原来8080的connector
<Connector port="8080" URIEncoding="UTF-8" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" /> -->
<!-- 新增如下connector -->
<Connector protocol= "org.apache.coyote.http11.Http11NioProtocol"
port= "8080" maxThreads= "200" URIEncoding= "UTF-8"
scheme= "https" secure= "true" SSLEnabled= "true"
keystoreFile= "/ssl/server.keystore"
keystorePass= "DwpPAd23xzvZTn09RmMuZKe3T4FeXfhM"
clientAuth= "false" sslProtocol= "TLS" />
Copy ④拷贝nginx的证书到每个应用的容器中,使用keytools工具把nginx证书添加为jdk的白名单:
1
2
3
4
# 假设你nginx的ip为10.0.0.1,并且证书被拷贝到了容器的/root目录,$JAVA_HOME已经到了jre的目录(如果没到的话需要增加一级jre路径)
$ keytool -keystore $JAVA_HOME /lib/security/cacerts -import -alias 10.0.0.1 -file /root/10.0.0.1.crt
# 输入默认密码,这里只需要输入一次密码,如果你需要输入两次说明你的路径不对
$ changeit
Copy ⑤修改应用的配置文件:
一般应用的配置文件都在/srv/tomcat8/webapps/<应用名>/WEB-INF/classes或者/srv/tomcat8/webapps/<应用名>/WEB-INF/classes/config,将应用间调用的地址改成https。
⑥cas_client会校验证书的合法性,由于是我们自己签发的证书,所以铁定会报错
1
ERROR [ https - jsse - nio - 8080 - exec - 8 ] org . jasig . cas . client . util . CommonUtils . getResponseFromServer - SSL error getting response from host xx . xx . xx . xx: Error Message: No subject alternative names present javax . net . ssl . SSLHandshakeException: No subject alternative names present
Copy 拷贝cas_client的补丁(点我下载 ),到容器里面,解压到/srv/tomcat8/webapps/<应用名>/WEB-INF/classes/com/geostar/gfstack/util目录
1
2
3
$ mkdir -p /srv/tomcat8/webapps/<应用名>/WEB-INF/classes/WEB-INF/classes/com/geostar/gfstack/util
$ mv /root/com/geostar/gfstack/util/TrustCASServerSSLListener.class /srv/tomcat8/webapps/<应用名>/WEB-INF/classes/WEB-INF/classes/com/geostar/gfstack/util/
$ mv /root/com/geostar/gfstack/util/TrustCASServerSSLListener\$ TrustAllManager.class /srv/tomcat8/webapps/<应用名>/WEB-INF/classes/WEB-INF/classes/com/geostar/gfstack/util/
Copy 然后配置/srv/tomcat8/webapps/<应用名>/WEB-INF/web.xml,增加监听这个类:
1
2
3
<listener>
<listener-class> com.geostar.gfstack.util.TrustCASServerSSLListener</listener-class>
</listener>
Copy ⑦重启应用