Nginx SSL+tomcat集羣,request.getScheme() 取到https正確的協議

公司之前用的是http,但是出於蘋果app審覈和服務器安全性問題,要改爲https,我們公司用的是沃通的ssl,按照沃通的官方文檔提供的步驟完成服務器的配置。 架構上使用了 Nginx +tomcat 集羣, 且nginx下配置了SSL,tomcat 沒有配置SSL,項目使用https協議。

配置成功後明明是https url請求,發現 log裏面,tomcat獲取scheme的時候,一直是http,而不是想像中的https

[plain] view plain copy

0415 16:01:10 INFO  (PaymentInterceptor.java:44) preHandle() - requestStringForLog:    {  
        "request.getRequestURL():": "http://m.xxx.com/payment/paymentChannel?id=212&s=a84485e0985afe97fffd7fd7741c93851d83a4f6",  
        "request.getMethod:": "GET",  
        "_parameterMap":         {  
            "id": ["212"],  
            "s": ["a84485e0985afe97fffd7fd7741c93851d83a4f6"]  
        }  
    }  

request.getRequestURL() 輸出出來的 一直是

http://m.xxx.com/payment/paymentChannel?id=212&s=a84485e0985afe97fffd7fd7741c93851d83a4f6

但是瀏覽器中的URL卻是

https://m.xxx.com/payment/paymentChannel?id=212&s=a84485e0985afe97fffd7fd7741c93851d83a4f6

下面我們進一步研究發現,java API上寫得很清楚:

getRequestURL():

[plain] view plain copy

Reconstructs the URL the client used to make the request.   

The returned URL contains a protocol, server name, port number, and server path,   
but it does not include query string parameters.  

也就是說, getRequestURL() 輸出的是不帶query string的路經(含協議,端口,server path等信息).

並且還發現

[java] view plain copy

request.getScheme()  //總是 http,而不是實際的http或https  
request.isSecure()  //總是false(因爲總是http)  
request.getRemoteAddr()  //總是 nginx 請求的 IP,而不是用戶的IP  
request.getRequestURL()  //總是 nginx 請求的URL 而不是用戶實際請求的 URL  
response.sendRedirect( 相對url )  //總是重定向到 http 上 (因爲認爲當前是 http 請求)  

那麼解決方案有沒有呢,答案是肯定的,其實解決方法非常的簡單,只需要分別配置一下 Nginx 和 Tomcat 就好了,而不用從程序代碼上修改。

1.配置nginx的轉發項,配置文件爲proxy.conf,內容如下:

[plain] view plain copy

proxy_connect_timeout 300s;  
proxy_send_timeout 900;  
proxy_read_timeout 900;  
proxy_buffer_size 32k;  
proxy_buffers 4 64k;  
proxy_busy_buffers_size 128k;  
proxy_redirect off;  
proxy_hide_header Vary;  
proxy_set_header Accept-Encoding '';  
proxy_set_header Referer $http_referer;  
proxy_set_header Cookie $http_cookie;  
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;起到了關鍵性的作用。

2.配置tomcat,配置文件爲server.xml,內容如下:

[plain] view plain copy

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE server-xml [  
<!ENTITY vhost-localhost SYSTEM "file:///usr/local/tomcat-interface/conf/vhost/localhost.xml">  
]>  
<Server port="8006" shutdown="SHUTDOWN">  
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>  
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>  
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>  
  <Listener className="org.apache.catalina.core.AprLifecycleListener"/>  

  <GlobalNamingResources>  
    <Resource name="UserDatabase" auth="Container"  
              type="org.apache.catalina.UserDatabase"  
              description="User database that can be updated and saved"  
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"  
              pathname="conf/tomcat-users.xml" />  
  </GlobalNamingResources>  

  <Service name="Catalina">  
    <Connector port="8080"  
              protocol="org.apache.coyote.http11.Http11AprProtocol"  
              connectionTimeout="20000"  
              redirectPort="8443"  
              maxThreads="1000"  
              minSpareThreads="20"  
              acceptCount="1000"  
              debug="0"  
              disableUploadTimeout="true"  
          useBodyEncodingForURI="true"  
              enableLookups="false"  
              URIEncoding="UTF-8" />  
    <Engine name="Catalina" defaultHost="localhost">  
      <Valve className="org.apache.catalina.valves.RemoteIpValve"  
        remoteIpHeader="X-Forwarded-For"  
        protocolHeader="X-Forwarded-Proto"  
        protocolHeaderHttpsValue="https"/>  
      <Realm className="org.apache.catalina.realm.LockOutRealm">  
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"  
               resourceName="UserDatabase"/>  
      </Realm>  
      &vhost-localhost;  
    </Engine>  
  </Service>  
</Server>  

其中關鍵的語句爲:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章