由於客戶端和web服務器之間增加了中間層,因此web服務器無法直接拿到客戶端的ip,通過$remote_addr變量拿到的將是反向代理服務器的ip地址。
1、安裝--with-http_realip_module
要想在程序中取得真實的IP,需對nginx重新編譯,新增--with-http_realip_module選項,操作如下:
cd /home/xxx/dev/nginx-1.10.2/ ./configure --with-http_realip_module make make install
#查看--with-http_realip_module是否安裝成功
cd /usr/local/nginx/sbin
sudo ./nginx -V
注意:安裝前nginx記得先關閉,安裝完畢再重啟。
2、相關配置
location / { proxy_pass http://lotmall; proxy_buffering on; set_real_ip_from 192.168.1.118; #指定接收來自哪個代理發送的IP head,可以是單個IP或者IP段 real_ip_header X-Real-IP; proxy_connect_timeout 30; proxy_read_timeout 30; proxy_send_timeout 30; }
3、nginx打印用戶真實IP
http { log_format main '$proxy_add_x_forwarded_for - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /usr/local/nginx/logs/access.log main; }
因為默認用的$remote_addr打印的是代理服務器的IP,我們不需要這個,所以我們使用代替了它的$http_x_forwarded_for 就可以打印出真實用戶的IP了。
4、Java獲取客戶端真實IP方法
/** * 請求獲取客戶端的真實IP地址 * * @param request * @return * @author jqlin */ public static String getRealIpAddress(HttpServletRequest request) { String ipAddress = request.getHeader("x-forwarded-for"); if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("Proxy-Client-IP"); } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("WL-Proxy-Client-IP"); } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getRemoteAddr(); if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) { // 根據網卡取本機配置的IP try { InetAddress inet = InetAddress.getLocalHost(); ipAddress = inet.getHostAddress(); } catch (UnknownHostException e) { log.error("根據網卡獲取本機配置的IP異常", e); } } } // 對於通過多個代理的情況,第一個IP為客戶端真實IP,多個IP按照','分割 if (ipAddress != null && ipAddress.indexOf(",") > 0) { // "***.***.***.***".length() ipAddress = ipAddress.split(",")[0]; } return ipAddress; }
