Nginx 作为前端反向代理或者负载均衡,Tomcat 不需要自己处理 https,https 由 Nginx 处理:
- 用户首先和 Nginx 建立连接,完成 SSL 握手
- 而后 Nginx 作为代理以 http 协议将请求转发给 Tomcat 处理
- Nginx 再把 Tomcat 的输出通过 SSL 加密发回给用户
Tomcat 只是在处理 http 请求而已 (默认监听 8080 端口)。因此,这种情况下不需要配置 Tomcat 的 SSL,只需要配置 Nginx 的 SSL,Tomcat 和 Nginx 需要配置以下几项:
Nginx 中启用 https:
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
34
35
36
37http {
include mime.types;
default_type text/html;
gzip on;
gzip_types text/css text/x-component application/x-javascript application/javascript text/javascript text/x-js text/richtext image/svg+xml text/plain text/xsd text/xsl text/xml image/x-icon;
sendfile on;
# Tomcat 服务器集群
upstream app_server {
server 127.0.0.1:8080 weight=4;
server 127.0.0.1:8081 weight=2;
server 127.0.0.1:8082 weight=1;
}
server {
listen 443 ssl; # https 的默认端口是 443
charset utf-8;
server_name www.xtuer.com; # host_name of URL
# 启用 https
ssl_certificate /Users/Biao/Desktop/cert/server.crt;
ssl_certificate_key /Users/Biao/Desktop/cert/server.key;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 把 https 的协议告知 Tomcat,否则 Tomcat 可能认为是 http 的请求
proxy_set_header X-Forwarded-Proto $scheme;
# 请求转发给 Tomcat 集群处理
proxy_pass http://app_server;
}
}
}关键是以下几项:
- listen port ssl
- ssl_certificate
- ssl_certificate_key
- X-Forwarded-Proto
Tomcat 的 server.xml 的 Host 中配置 Valve:
1
2
3<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For" protocolHeader="X-Forwarded-Proto" protocolHeaderHttpsValue="https"/>
</Host>- X-Forwarded-Proto 是为了正确地识别实际用户发出的协议是 http 还是 https
- X-Forwarded-For 是为了获得实际用户的 IP
- 如果不配置它们,则在 redirect 的时候仍然会使用 http 而不是 https
注意: 当使用非 443 端口,如 9443 时,需要修改 2 个地方:
1
2
3
4
5
6
7
8
9
10
11Nginx: Host 中增加 $server_port
listen 9443 ssl;
proxy_set_header Host $host:$server_port;
Tomcat: 必须配置 httpsServerPort,否则 request.getServerPort() 仍然返回 443
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="X-Forwarded-For"
protocolHeader="X-Forwarded-Proto"
protocolHeaderHttpsValue="https"
httpsServerPort="9443"
/>
自签证书
https 需要的证书可以去购买,也可以申请免费的证书,不过我们也可以自签一个证书在本地进行测试 (自签的证书在访问时需要用户手动确认信任证书才能继续访问),步骤如下:
openssl genrsa -des3 -out server.key 1024
1
2
3
4
5
6Generating RSA private key, 1024 bit long modulus
.....++++++
..++++++
e is 65537 (0x10001)
Enter pass phrase for server.key: # 输入密码 changeit
Verifying - Enter pass phrase for server.key: # 输入密码 changeitopenssl req -new -key server.key -out server.csr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20Enter pass phrase for server.key: # 输入上面设置的密码 changeit
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN # 国家的代码,中国输入 CN 即可
State or Province Name (full name) [Some-State]:Beijing # 省
Locality Name (eg, city) []:Beijing # 城市
Organization Name (eg, company) [Internet Widgits Pty Ltd]:xo # 公司,随意
Organizational Unit Name (eg, section) []:xo # 部门,随意
Common Name (e.g. server FQDN or YOUR name) []:xtuer.com # 可以随意输入,不一定要是域名
Email Address []: # 回车,不需要输入
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: # 回车,不需要输入
An optional company name []: # 回车,不需要输入cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
1
2Enter pass phrase for server.key.org: # 输入上面设置的密码 changeit
writing RSA keyopenssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
1
2
3Signature ok
subject=/C=CN/ST=Beijing/L=Beijing/O=xo/OU=xo/CN=xtuer.com
Getting Private key把生成的 server.crt 和 server.key 配置到 Nginx
1
2
3
4
5
6
7
8# [1]
listen 443 ssl; # https 的默认端口是 443
# ssl on;
ssl_certificate /Users/Biao/Desktop/cert/server.crt;
ssl_certificate_key /Users/Biao/Desktop/cert/server.key;
# [2] 把 https 的协议告知 Tomcat,否则 Tomcat 可能认为是 http 的请求
proxy_set_header X-Forwarded-Proto $scheme;加载 Nginx 配置 (以 Mac 下 MAMP 为例)
- 测试配置文件语法:
sudo /Applications/MAMP/Library/bin/nginxctl -t
- 重新加载配置文件:
sudo /Applications/MAMP/Library/bin/nginxctl -s reload
- 测试配置文件语法:
使用 https 访问网站,例如 https://www.xtuer.com
浏览器会提示证书不可信任,选择信任即可
1
2
3Your connection is not private
Attackers might be trying to steal your information from www.xtuer.com (for example, passwords, messages, or credit cards). NET::ERR_CERT_AUTHORITY_INVALID