1. 程式人生 > >Nginx SSL 結合Tomcat 重定向URL變成HTTP的問題

Nginx SSL 結合Tomcat 重定向URL變成HTTP的問題

start lower lis 沒有 con 成了 info ipv 場景

http://www.siven.net/posts/d925bb5d.html

***********************************************

問題描述

由於要配置服務器(Nginx + Tomcat)的SSL的問題(Nginx同時監聽HTTPHTTPS),但是,如果用戶訪問的是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);

測試結果與重定向一致, 無異常情況;

測試總結

實際應用場景中,如果要求HTTPHTTPS協議共存的時候(請求的協議與響應的協議一致)就會出現HTTP請求被強轉為HTTPS,嘗試將Nginx配置proxy_redirect http:// https://;註釋,最終使用HTTPS協議亦無法正常跳轉;

實踐二:Tomcat新增配置

不修改Nginx的情況下, 僅對Tomcat配置進行調整

server.xmlEngine模塊下面配置多一個以下的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的問題