Java獲取訪問者Ip並限制Ip訪問頁面


原文鏈接:https://www.zjhuiwan.cn/info/20200330/4006602464505049.html

最近遇到一個需求,一個只能內網訪問的網站,需要限制ip訪問。就是網站內的部分文章只有白名單內的ip才能打開。因為是靜態化的網站,所有文章都是靜態html頁面。所以首先想到的就是直接js獲取訪問者ip然后再判斷是否在白名單內,不在白名單內就到沒有權限頁面。

但是JS獲取內網Ip還是比較麻煩的,查到幾個方法最后試了都不行。

記錄下查到的幾個方法和最后實現的方法。

JS獲取外網ip的方法:

//最簡單的獲取外網ip的方法。可以直接用,但是沒啥用..
<script src="http://pv.sohu.com/cityjson?ie=utf-8"></script> <script>     document.write(returnCitySN["cip"]); </script>

JS獲取內網Ip的方法://有些瀏覽器獲取到的加密ip段有問題,所以當其時期

function getIP(callback) {         let recode = {};         let RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;         // 如果不存在則使用一個iframe繞過         if (!RTCPeerConnection) {             // 因為這里用到了iframe,所以在調用這個方法的script上必須有一個iframe標簽             // <iframe id="iframe" sandbox="allow-same-origin" style="display:none;"></iframe>             let win = iframe.contentWindow;             RTCPeerConnection = win.RTCPeerConnection || win.mozRTCPeerConnection || win.webkitRTCPeerConnection;         }         //創建實例,生成連接         let pc = new RTCPeerConnection();         // 匹配字符串中符合ip地址的字段         function handleCandidate(candidate) { debugger;             let ip_regexp = /([0-9]{1,3}(\.[0-9]{1,3}){3}|([a-f0-9]{1,4}((:[a-f0-9]{1,4}){7}|:+[a-f0-9]{1,4}){6}))/;             let ip_isMatch = candidate.match(ip_regexp)[1];             if (!recode[ip_isMatch]) {                 callback(ip_isMatch);                 recode[ip_isMatch] = true;             }         }         //監聽icecandidate事件         pc.onicecandidate = (ice) => {             if (ice.candidate) {                 handleCandidate(ice.candidate.candidate);             }         };         //建立一個偽數據的通道         pc.createDataChannel('');         pc.createOffer((res) => {             pc.setLocalDescription(res);         }, () => {});         //延遲,讓一切都能完成         setTimeout(() => {             let lines = pc.localDescription.sdp.split('\n');             lines.forEach(item => {                 if (item.indexOf('a=candidate:') === 0) {                     handleCandidate(item);                 }             })         }, 1000);     } getIP(function (ip) { alert(ip); });

利用WebRTC獲取真實內網Ip,WebRTC是一個支持網頁瀏覽器進行實時語音對話或視頻對話的API

由於WebRTC在建立連接過程中,會向對方發送本地地址SDP,因此可以通過訪問SDP獲得訪問者的IP

但是有些瀏覽器用不了,所以還是放棄這種方式了。

 

 

最后還是覺得用Java來實現比較好吧,前端文章頁寫個ajax,每次進入文章先判斷文章是否需要限制IP訪問,如果需要就請求下后端,后端獲取Ip判斷是否在白名單內。注意ajax要用同步。

Java獲取訪問者Ip方法:

 String ip = request.getHeader("x-forwarded-for");         if (ip == null || ip.length() == 0 || "nuknown".equalsIgnoreCase(ip)) {             ip = request.getHeader("Proxy-Client-IP");         }         if (ip == null || ip.length() == 0 || "nuknown".equalsIgnoreCase(ip)) {             ip = request.getHeader("WL-Proxy-Client-IP");         }         if (ip == null || ip.length() == 0 || "nuknown".equalsIgnoreCase(ip)) {             ip = request.getRemoteAddr();         }         System.out.println(ip);

完整代碼

    
/**      * 判斷文章是否有權可看      *       * @param map      * @return      */     @RequestMapping("/isIntranet.do")     @ResponseBody     public String isIntranet(ServletRequest request, ServletResponse response) {         Map<String, Object> map = new HashMap<String, Object>();         HttpServletRequest req = (HttpServletRequest)request;         HttpServletResponse resp = (HttpServletResponse)response;         // 判斷訪問者Ip是否白名單內         boolean flag = isIPOK(req, resp);         System.out.println(flag);         if (flag) {             return "true";         } else {             return "false";         }     }     private boolean isIPOK(HttpServletRequest request, HttpServletResponse response) {         // String accessIP = IPUtil.getUserIp(request);         String ip = request.getHeader("x-forwarded-for");         if (ip == null || ip.length() == 0 || "nuknown".equalsIgnoreCase(ip)) {             ip = request.getHeader("Proxy-Client-IP");         }         if (ip == null || ip.length() == 0 || "nuknown".equalsIgnoreCase(ip)) {             ip = request.getHeader("WL-Proxy-Client-IP");         }         if (ip == null || ip.length() == 0 || "nuknown".equalsIgnoreCase(ip)) {             ip = request.getRemoteAddr();         }         System.out.println(ip);         return isLAN(ip);     }     // 是否為內網網段     public boolean isLAN(String ip) {         if ("127.0.0.1".equals(ip)) {             return true;         }         boolean result = true;         try {             Properties prop = new Properties();             //獲取設置Ip段的配置文件             InputStream in = this.getClass().getClassLoader().getResourceAsStream("ipConfig.properties");             prop.load(in);             // 遍歷取值             Set<Object> objects = prop.keySet();             for (Object object : objects) {                 String ipNot = new String(prop.getProperty((String)object).getBytes("iso-8859-1"), "gbk");                 System.out.println(ipNot);                 /*result = ipIsValid("192.168.8.78-192.168.255.255", ip) || ipIsValid("172.16.0.0-172.31.255.255", ip)                     || ipIsValid("10.0.0.0-10.255.255.255", ip);*/                 result = ipIsValid(ipNot, ip);             }             in.close();         } catch (IOException e) {             e.printStackTrace();         }         return result;     }          //校驗Ip是否包含在Ip段內     public static boolean ipIsValid(String ipSection, String ip) {         if (ipSection == null) {             throw new NullPointerException("IP段不能為空!");         }         if (ip == null) {             throw new NullPointerException("IP不能為空!");         }         ipSection = ipSection.trim();         ip = ip.trim();         final String REGX_IP =             "((25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)";         final String REGX_IPB = REGX_IP + "\\-" + REGX_IP;         if (!ipSection.matches(REGX_IPB) || !ip.matches(REGX_IP)) {             return false;         }         int idx = ipSection.indexOf('-');         idx = idx < 0 ? ipSection.length() : idx;         String[] sips = ipSection.substring(0, idx).split("\\.");         String[] sipe = ipSection.substring(idx + 1).split("\\.");         String[] sipt = ip.split("\\.");         long ips = 0L, ipe = 0L, ipt = 0L;         for (int i = 0; i < 4; ++i) {             ips = ips << 8 | Integer.parseInt(sips[i]);             ipe = ipe << 8 | Integer.parseInt(sipe[i]);             ipt = ipt << 8 | Integer.parseInt(sipt[i]);         }         if (ips > ipe) {             long t = ips;             ips = ipe;             ipe = t;         }         return ips <= ipt && ipt <= ipe;     }

以上方法均來自網絡,親測有效,記錄於此。

I am just a porter


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM