Nginx SSL 結合Tomcat 重定向URL變成HTTP的問題
http://www.siven.net/posts/d925bb5d.html
***********************************************
問題描述
由於要配置服務器(Nginx + Tomcat)的SSL的問題(Nginx同時監聽HTTP
和HTTPS
),但是,如果用戶訪問的是HTTPS
協議,然後Tomcat進行重定向的時候,卻變成了HTTP
.
逐步實踐過程
在網上找了一些資料,有些是通過修改Nginx配置即可解決,也有只對Tomcat配置進行調整解決的… 各說不一,以下對嘗試的解決過程進行記錄:
實踐一:Nginx新增配置
HTTP協議制轉為https
Nginx代理的配置,要添加以下內容:
location / {
proxy_pass http://test-server;
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;
# 作用是對發送給客戶端的URL進行修改, 將http協議強制轉為https
proxy_redirect http:// https://;
}
為了方便測試proxy_redirect
強制轉換, http(80)、https(443)共存
server {
listen 80;
listen 443 ssl;
...
}
重定向測試
-
JAVA CODE:
HttpServletResponse resp = (HttpServletResponse)response;
resp.sendRedirect("/static/html/index.html");
使用HTTP
協議訪問nginx
代理地址之後,URL被重定向為HTTPS
協議了, 如下圖所示:
當然直接使用HTTPS協議訪問, 肯定也是沒有問題的,如下圖所示:
轉發測試
-
JAVA CODE:
HttpServletResponse resp = (HttpServletResponse)response;
req.getRequestDispatcher("/static/html/index.html").forward(request, response);
測試結果與重定向一致, 無異常情況;
測試總結
實際應用場景中,如果要求HTTP
與HTTPS
協議共存的時候(請求的協議與響應的協議一致)就會出現HTTP
請求被強轉為HTTPS
,嘗試將Nginx配置proxy_redirect http:// https://;
註釋,最終使用HTTPS
協議亦無法正常跳轉;
實踐二:Tomcat新增配置
不修改Nginx的情況下, 僅對Tomcat配置進行調整
在server.xml
的Engine
模塊下面配置多一個以下的Valve
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For" protocolHeader="X-Forwarded-Proto" protocolHeaderHttpsValue="https"/>
重定向測試
使用HTTPS
協議訪問時,最終被重定向到HTTP
轉發測試
使用HTTPS
協議訪問,轉發動作未出現問題
測試總結
重定向的時候, HTTPS
協議被轉為HTTP
,測試結果不通過。
實踐三:終極方案
Nginx 配置
對過程一Nginx配置進行調整註釋或刪除proxy_redirect
,最終如下:
location / {
proxy_pass http://test-server;
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;
}
Tomcat 配置
參看:Tomcat配置
測試過程
HTTP協議請求
HTTPS協議請求
測試結果
測試通過,無論使用HTTP訪問還是HTTPS訪問,最終返回都是根據請求的協議進行響應,問題解決。
完整配置
- Nginx
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream test-server {
server 10.15.16.6:8280 weight=1;
}
server {
listen 80;
listen 443 ssl;
server_name localhost;
#ssl_certificate cert.pem;
#ssl_certificate_key cert.key;
ssl_certificate server.crt;
ssl_certificate_key server.key;
# ssl_session_cache shared:SSL:1m;
#ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
location / {
proxy_pass http://test-server;
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_redirect http:// https://;
}
}
}
//處理代碼段
domainName = request.getRequestURL().toString(); String X_Forwarded_Proto = httpRequest.getHeader("X-Forwarded-Proto"); if(StringUtils.isNotBlank(X_Forwarded_Proto)){ if(X_Forwarded_Proto.toLowerCase().contains("https") && !domainName.toLowerCase().startsWith("https://")){ domainName = "https://" + domainName.substring(7); } }
Nginx SSL 結合Tomcat 重定向URL變成HTTP的問題