应用场景:
部署Spring Boot Admin监控服务,使用Nginx做反向代理,并在nginx上配置SSL证书,采用HTTPS协议访问。配置如下:
upstream serviceAdmin {
server 172.16.0.101:8911;
server 172.16.0.102:8911;
}
server {
listen 8910 ssl http2;
server_name test.xxx.com;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_certificate /etc/ssl/STAR.xxx.com.crt;
ssl_certificate_key /etc/ssl/STAR.xxx.com.key;
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_session_cache shared:serviceAdminSSL:10m;
ssl_session_timeout 30m;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://serviceAdmin;
proxy_set_header Host $http_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-Host $http_host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect http:// $scheme://;
proxy_next_upstream off;
proxy_connect_timeout 10;
proxy_read_timeout 90;
proxy_send_timeout 90;
}
}
问题描述:
部署完成后使用浏览器访问https://test.xxx.com:8910/serviceAdmin/login进行登录
输入用户名密码进行登录,然后浏览器就提示400错误。
浏览器地址栏中的https协议变成了http协议。
原因分析:
打开浏览器控制台,查看请求信息,发现有接口报错。
仔细观察报错的接口,发现请求地址中的协议是http,不是https,服务器只接收https的请求,所以出现了400错误。再看上面的login请求,这个请求是成功的。
我们看到登录请求的请求地址是正确的,http状态码是302,这会导致浏览器重定向。浏览器是根据响应头中location的值重定向,而这里的地址却是http开头的,这就是为什么登录成功后浏览器请求地址的协议变成了http。 那为什么服务端响应头中location的地址会是http协议呢?原因是客户端请求经过Nginx代理后,从Nginx到被代理服务的请求用了http协议
proxy_pass http://serviceAdmin;
所以被代理服务认为客户端请求的协议是http,返回重定向信息中的地址也用了http,浏览器根据响应结果向http协议的地址跳转时就出现了错误。
解决方案:
使用Nginx的proxy_redirect指令将被代理服务响应头中Location和Refresh头中地址的协议改成https。
location / {
proxy_pass http://serviceAdmin;
proxy_set_header Host $http_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-Host $http_host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect http:// $scheme://;
proxy_next_upstream off;
proxy_connect_timeout 10;
proxy_read_timeout 90;
proxy_send_timeout 90;
}
proxy_redirect指令就是用来改变被代理服务响应头中Location和Refresh头的值。$scheme是一个变量,是客户端请求中的协议。这样一来客户端请求用什么协议,响应头中Location地址也用什么协议。重新部署后,成功解决问题。
软件版本:
Nginx:1.12.1
|