公司之前用的是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>
其中關鍵的語句爲: