系统架构为:Nginx +tomcat 集群,目前要在nginx上配置ssl(注意不是在tomcat上配置ssl),实现https和http协议双支持,并且不能修改tomcat应用的任何代码。
借用了一张网络图如下:
开始的时候遇到了坑,部署好了nginx,发现tomcat下面的api接口通过https访问时OK,但是用https访问里面的网站时,页面可以加载,但是css和js样式加载不出来。经过确认,网页内的css文件地址仍然是 http协议的,而https协议不允许内部夹杂http协议的引用,所以页面显示混乱。后来经过确实,原来页内css和js文件是应用程序拼装出来的url地址,如下代码:
String ctx = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path;
其中request.getScheme()获取到的是http,所以肯定是错了!
那么正确配置如下:
1,通过阿里云控制台的“产品与服务”,申请购买CA证书,选择了里面的wosign(目前单二级域名证书可以免费送一年)。选择 xx.xxx.com这一个免费用一年。
2,购买免费版完成以后,在阿里云控制台下载证书,包含两个 xxx.key和xxx.pem文件
3,在nginx服务器里选择一个目录将两个文件放进去(配置nginx配置文件时要用)
4,修改nginx配置文件:默认为/usr/local/nginx/conf/nginx.conf
server {
listen 443 ssl;
server_name xxx.xxx.com;
#ssl on;
ssl_certificate /usr/share/xxx/xxx/xxxx.pem;
ssl_certificate_key /usr/share/xxx/xxx/xxxx.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 25m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://xxxxxxxxxx;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
具体里面的配置项无需多说了吧,不会的自己去查一下,关键要提一个很重要的参数传递配置就是
proxy_set_header X-Forwarded-Proto $scheme;
这句话将“https”传递给tomcat。tomcat接收到以后传递给内部部署的应用,用来组装url。
5,重启nginx ./nginx -s reload
6,修改tomcat配置文件,打开/xxxx/tomcat/conf/server.xml
在 <Engine name="Catalina" defaultHost="localhost">节点下面
加入:
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="X-Forwarded-For"
protocolHeader="X-Forwarded-Proto"
protocolHeaderHttpsValue="https"/>
原理是通过参数传递给tomcat内的引用https信息,程序内组装url常用如下代码时:
<%
String path = request.getContextPath();
String ctx = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path;
request.setAttribute("ctx", ctx);
%>
request.getScheme()可以通过传递参数内的X-Forwarded-Proto获取到https协议。
当然对于tomcat来说,这个配置是完全忽略外部到底是http还是https的。所以内部程序完全不需要修改代码。tomcat实际处理的也永远都是http协议
7,重启tomcat