Nginx反向代理後應用程序獲取客戶端真實IP

 

Nginx反向代理後,Servlet應用經過request.getRemoteAddr()取到的IP是Nginx的IP地址,並不是客戶端真實IP,經過request.getRequestURL()獲取的域名、協議、端口都是Nginx訪問Web應用時的域名、協議、端口,而非客戶端瀏覽器地址欄上的真實域名、協議、端口。apache

Nginx的反向代理其實是客戶端和真實的應用服務器之間的一個橋樑,客戶端(通常是瀏覽器)訪問Nginx服務器,Nginx再去訪問Web應用服務器。對於Web應用來講,此次HTTP請求的客戶端是Nginx而非真實的客戶端瀏覽器,若是不作特殊處理的話,Web應用會把Nginx看成請求的客戶端,獲取到的客戶端信息就是Nginx的一些信息。瀏覽器

解決這個問題要從兩個方面來解決: 
1. 因爲Nginx是代理服務器,全部客戶端請求都從Nginx轉發到Tomcat,若是Nginx不把客戶端真實IP、域名、協議、端口告訴Tomcat,那麼Tomcat應用是永遠不會知道這些信息的,因此須要Nginx配置一些HTTP Header來將這些信息告訴被代理的Tomcat; 
2. Tomcat這一端,不能再傻乎乎的獲取直接和它鏈接的客戶端(也就是Nginx)的信息,而是要從Nginx傳遞過來的HTTP Header中獲取客戶端信息。

tomcat

 

修改Nginx配置:
服務器

1 -- 在location/ 增長如下屬性: 2 proxy_set_header Host $http_host; 3 proxy_set_header X-Real-IP $remote_addr; 4 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 5 proxy_set_header X-Forwarded-Proto $scheme;

示例:spa

 1     location /masl {  2         proxy_pass http://asl_server/masl; 
 3  proxy_redirect off; 
 7 proxy_set_header X-Forwarded-Proto $scheme; 8 proxy_set_header Host $host:$server_port; 10 proxy_set_header X-Real-IP $remote_addr; 11 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 12  client_max_body_size 100m; 13  client_body_buffer_size 128k; 14             proxy_connect_timeout 90; 15             proxy_send_timeout 90; 16             proxy_read_timeout 90; 17  proxy_buffer_size 4k; 18             proxy_buffers 4 32k; 19  proxy_busy_buffers_size 64k; 20  proxy_temp_file_write_size 256k; 21         }

 

解釋如下上面的配置,以上配置是在Nginx反向代理的時候,添加一些請求Header。 
1. Host包含客戶端真實的域名和端口號; 
2. X-Forwarded-Proto表示客戶端真實的協議(http仍是https); 
3. X-Real-IP表示客戶端真實的IP; 
4. X-Forwarded-For這個Header和X-Real-IP相似,但它在多層代理時會包含真實客戶端及中間每一個代理服務器的IP。代理

配置到這一步後,還不能完全解決問題。tomcat也須要配置code

若是你在網上搜索「Java如何獲取客戶端真實IP」,搜索到的解決方案大可能是經過獲取HTTP請求頭request.getHeader("X-Forwarded-For")或request.getHeader("X-Real-IP")來實現,也就是上面在Nginx上配置的Header,這種方案獲取的結果的確是正確的,但以爲並不優雅。由於既然Servlet API提供了request.getRemoteAddr()方法獲取客戶端IP,那麼不管有沒有用反向代理對於代碼編寫者來講應該是透明的。下面介紹一種更加優雅的方式。server


使用Tomcat做爲應用服務器,能夠經過配置Tomcat的server.xml文件,在Host元素內最後加入:便可xml

<Valve className="org.apache.catalina.valves.RemoteIpValve" />
相關文章
相關標籤/搜索