java后端获取客户端(用户)真实ip,原理
java后端獲取客戶端真實ip,原理:
一般都是下面代碼中的做法:但很多人只知道這樣能拿到,稍微有改動就不知道怎么辦了
看看網上的各種說法,接下來容我一一講解,如有紕漏,敬請指正。
public static String getIpAdrress(HttpServletRequest request) {String ip = null;//X-Forwarded-For:Squid 服務代理String ipAddresses = request.getHeader("X-Forwarded-For");System.out.println("====ipAddresses:"+ipAddresses);Enumeration<String> headerNames = request.getHeaderNames();while (headerNames.hasMoreElements()) {//打印所有頭信息String s = headerNames.nextElement();String header = request.getHeader(s);System.out.println(s+"::::"+header);}System.out.println("headerNames:"+JSON.toJSONString(headerNames));System.out.println("RemoteHost:"+request.getRemoteHost());System.out.println("RemoteAddr:"+request.getRemoteAddr());String unknown = "unknown";if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {//Proxy-Client-IP:apache 服務代理ipAddresses = request.getHeader("Proxy-Client-IP");}if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {//WL-Proxy-Client-IP:weblogic 服務代理ipAddresses = request.getHeader("WL-Proxy-Client-IP");}if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {//HTTP_CLIENT_IP:有些代理服務器ipAddresses = request.getHeader("HTTP_CLIENT_IP");}if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {//X-Real-IP:nginx服務代理ipAddresses = request.getHeader("X-Real-IP");}//有些網絡通過多層代理,那么獲取到的ip就會有多個,一般都是通過逗號(,)分割開來,并且第一個ip為客戶端的真實IPif (ipAddresses != null && ipAddresses.length() != 0) {ip = ipAddresses.split(",")[0];}//還是不能獲取到,最后再通過request.getRemoteAddr();獲取if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {ip = request.getRemoteAddr();}return ip;}講講上面獲取用戶ip的代碼
首先有個基本概念,就是客戶端要想和服務端交互,就必須告訴服務端自己的ip,畢竟有TCP三次握手。
當然,這些都是普通用戶,特殊用戶會隱藏ip,這種暫且不說。
再從服務端說起,如果服務器直接把IP暴漏出去,那么request.getRemoteAddr()就能拿到客戶端ip。
但目前流行的架構中,基本上服務器都不會直接把自己的ip暴漏出去,一般前面還有一層或多層反向代理,常見的nginx居多。
加了代理后,相當于服務器和客戶端中間還有一層,這時候request.getRemoteAddr()拿到的就是代理服務器的ip了,并不是客戶端的ip。所以這種情況下,一般會在轉發頭上加X-Forwarded-For等信息,用來跟蹤原始客戶端的ip。
這時候,才會用上面的這些代碼。解釋下這些加上的信息:
X-Forwarded-For:
這是一個 Squid 開發的字段,只有在通過了HTTP代理或者負載均衡服務器時才會添加該項。 格式為X-Forwarded-For:client1,proxy1,proxy2,一般情況下,第一個ip為客戶端真實ip,后面的為經過的代理服務器ip。 上面的代碼注釋也說的很清楚,直接截取拿到第一個ip。Proxy-Client-IP/WL- Proxy-Client-IP:
這個一般是經過apache http服務器的請求才會有,用apache http做代理時一般會加上Proxy-Client-IP請求頭, 而WL-Proxy-Client-IP是他的weblogic插件加上的頭。 這種情況也是直接能拿到。HTTP_CLIENT_IP:
有些代理服務器也會加上此請求頭。X-Real-IP:
nginx一般用這個。總結
不知道你有沒有發現,上面這些頭信息,都是各做各的,沒有一個統一,所以代碼也就寫成了這樣,其實就是一個一個試唄。
所以指不定以后再來個什么代理服務器,頭信息是XX-xx-xx,那我們的代碼也要做相應的修改。
還有,這代碼只是一個大概的思想,具體情況具體對待,因為獲取不到請求頭這些ip的情況也不在少數,哪怕代理層以后都統一了,用戶層還有其他幺蛾子方法,就是不讓你知道他的ip,所以總的結論就是上有政策,下有對策。
舉例幾個常見的案例
1.服務端防刷
2.記錄用戶操作
等等,總之就是服務端監控和區分客戶端的,經常會用ip作為一個可靠指標
總結
以上是生活随笔為你收集整理的java后端获取客户端(用户)真实ip,原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [数据库]-----记一次mysql分库
- 下一篇: 大学生计算机二级大集报名最好,在校大学生