詳解Java Web如何限制訪問的IP的兩種方法
前一陣子因?yàn)樵谧鲰?xiàng)目時(shí)碰到了這個(gè)功能,現(xiàn)在好好總結(jié)一下,至于為什么要限制IP訪問,我就不多說了。然后百度了一下,現(xiàn)在主要有兩種方式去限制IP訪問,第一種是最簡單的方便的,第二種是通過過濾器來限制訪問。下面我簡單介紹一下第一種方式,著重介紹第二種。
第一種方式(Tomcat配置項(xiàng)配置允許或限制IP訪問)
這種是最簡單的快捷的,主要就涉及Tomcat的server.xml配置。
第一步:找到server.xml文件在哪,在Tomcat的目錄下的conf文件夾下。第二步:打開server.xml文件,找到Host節(jié)點(diǎn),在其中加上:
<Valve className='org.apache.catalina.valves.RemoteAddrValve' allow='127.0.0.1' deny=''/>
其中:className:表示java類名,必須是org.apache.catalina.valves.RemoteHostValve或org.apache.catalina.valves.RemoteAddrValve;allow:表示允許的IP,支持模糊(* )、正則,多個(gè)用,隔開;deny:表示限制的IP,支持模糊( *)、正則;多個(gè)用,隔開。注:如果是限制某一個(gè)站點(diǎn)(網(wǎng)站)則在Context節(jié)點(diǎn)中添加。第三步:重啟Tomcat。
第二種方式(通過Filter過濾器來配置允許或限制IP訪問)
(1)代碼實(shí)現(xiàn)的思路 通過增加配置文件properties,將允許訪問的IP按一定規(guī)則配置進(jìn)去;接下來再對(duì)配置文件(這里尚且叫做配置文件)進(jìn)行加載;然后再對(duì)配置文件的格式要求通過正則進(jìn)行校驗(yàn);其次將配置的IP通過一個(gè)集合進(jìn)行收集,可收集單條IP或一個(gè)IP的正則,因?yàn)槲覀冞@里需要用到模糊;最后對(duì)訪問者的IP與集合中的進(jìn)行比對(duì),比對(duì)通過則正常訪問,否則。反之。 在配置文件中提供三種最常見的IP配置方式:
單個(gè)IP地址的配置,多個(gè)之間用逗號(hào)或分好隔開;例如:192.168.1.50;127.0.0.1;IP地址區(qū)間方式的配置,多個(gè)區(qū)間用逗號(hào)或分好隔開;例如:172.20.32.10-172.20.32.11;172.20.32.88-172.20.32.89通配符,多個(gè)用逗號(hào)或分好隔開。例如:172.20.30.*
(2)具體實(shí)現(xiàn)代碼第一步:編寫配置文件/Test/src/com/config/ipConfig.properties;
#單個(gè)IP地址的配置,多個(gè)之間用逗號(hào)或分好隔開allowIP=192.168.1.50;127.0.0.1;#IP地址區(qū)間方式的配置,多個(gè)區(qū)間用逗號(hào)或分好隔開allowIPRange=172.20.32.10-172.20.32.11;172.20.32.88-172.20.32.89#通配符,多個(gè)用逗號(hào)或分好隔開allowIPWildcard=172.20.30.*;
第二步:新建Java類實(shí)現(xiàn)Filter;第三步:在web.xml中配置過濾器;
<!-- 過濾器 --> <!-- ip過濾器,過濾所有請求地址 --> <filter> <filter-name>IPFilter</filter-name> <filter-class>com.filter.IpFilter</filter-class> </filter> <filter-mapping> <filter-name>IPFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 結(jié)束過濾器 -->
第四步:我們需要聲明一個(gè)全局變量List來存放允許訪問的IP或正則式;
//聲明的代碼://用來存放允許訪問的ipprivate List<String> allowList = new ArrayList<String>();
第五步:需要對(duì)配置文件進(jìn)行加載;在方法init中
//加載的代碼://將文件轉(zhuǎn)化成流InputStream inputStream = IpFilter.class.getResourceAsStream('../config/ipConfig.properties');Properties properties = new Properties();//通過Properties對(duì)象實(shí)例加載流properties.load(inputStream);//獲取三種配置方式的值String allowIP = properties.getProperty('allowIP');String allowIPRange = properties.getProperty('allowIPRange');String allowIPWildcard = properties.getProperty('allowIPWildcard');
第六步:校驗(yàn)配置文件格式;在方法init中
//校驗(yàn)的部分代碼//如果為空,說明用戶沒添加該項(xiàng),不做處理if(allow == null || ''.equals(allow.trim())) {return true;} else {//在最后面沒有,或;的給添上if(!allow.endsWith(';') && !allow.endsWith(',')) {allow += ';';}//如果匹配,則返回trueif(pattern.matcher(allow).matches()) {return true;}}
第七步:獲取每種配置方式的IP;在方法init中
/* * 將每一種配置方法放置到allowList中 *///將第一種配置方法放到allowList中if(null != allowIP && !''.equals(allowIP.trim())) {String[] allowIPs = allowIP.split(',|;');for(String ip : allowIPs) {allowList.add(ip);}}//將第二種配置方法放到allowList中if(null != allowIPRange && !''.equals(allowIPRange.trim())) {//先進(jìn)行每一段的分割String[] allowIPRanges = allowIPRange.split(',|;');if(allowIPRanges.length > 0) {//對(duì)每一段進(jìn)行遍歷for(String allowRanges : allowIPRanges) {if(allowRanges != null && !''.equals(allowRanges.trim())) {//對(duì)該段的ip進(jìn)行解析String[] ips = allowRanges.split('-');if(ips.length > 0 && ips.length < 3) {String from = ips[0];//得到該段的起始ipString to = ips[1]; //得到該段的結(jié)束ip//獲取該ip段地址的前三段,因?yàn)槠鹗己徒Y(jié)束的ip的前三段一樣String share = from.substring(0, from.lastIndexOf('.')+1);//獲取該ip段的起始ip的最后一段int start = Integer.parseInt(from.substring(from.lastIndexOf('.')+1, from.length()));//獲取該ip段的結(jié)束ip的最后一段int end = Integer.parseInt(to.substring(to.lastIndexOf('.')+1, to.length()));for(int i=start; i<=end; i++) {String ip = share + String.valueOf(i);allowList.add(ip);}} else {throw new RuntimeException('配置文件有錯(cuò),請檢查!');}}}}}//將第三種配置方法放到allowList中if(allowIPWildcard != null && !''.equals(allowIPWildcard)) {//獲取每個(gè)含通配符的ip地址String[] allowIPWildcards = allowIPWildcard.split(',|;');if(allowIPWildcards.length > 0) {for(String ip : allowIPWildcards) {if(ip.indexOf('*') != -1) {//對(duì)*進(jìn)行替換ip = ip.replaceAll('*', '(25[0-5]|2[0-4]d|[0-1]d{2}|[1-9]?d)');allowList.add(ip);} else {throw new RuntimeException('配置文件有錯(cuò),請檢查!');}}}}
第八步:IP比對(duì),成功匹配就正常訪問,反之則跳到錯(cuò)誤頁面。這個(gè)因?yàn)槭窃谟脩粼L問時(shí)才進(jìn)行的步驟,需要在doFilter方法的編寫。
//獲取訪問的IP地址String remoteAddr = request.getRemoteAddr();//System.out.println('===============' + remoteAddr);//如果allowList為空,則認(rèn)為沒做限制,不為空則檢查是否限制if(allowList.size() == 0 || allowList == null) {filterChain.doFilter(request, response);} else {Boolean flag = false; //訪問標(biāo)志,默認(rèn)為false,限制訪問//進(jìn)行逐個(gè)檢查for(String regex : allowList){if(remoteAddr.matches(regex)){//ip沒被限制,正常訪問filterChain.doFilter(request, response);flag = true; //置為true,表示不限制訪問break;}}if(!flag) {//ip被限制,跳到指定頁面request.getRequestDispatcher('WEB-INF/success/error.jsp').forward(request, response);}}
附成功后截圖:
附完整代碼:
package com.filter;import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import java.util.List;import java.util.Properties;import java.util.regex.Pattern;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;/** * 過濾器 * 功能:對(duì)訪問者IP進(jìn)行限制訪問 * @author ouyang * @serial 20180728 * @version 1.0 */public class IpFilter implements Filter{//用來存放允許訪問的ipprivate List<String> allowList = new ArrayList<String>();@Overridepublic void init(FilterConfig arg0) throws ServletException {try {System.out.println('過濾器IpFilter開始初始化,功能:IP訪問限制');initConfig();} catch (IOException e) {e.printStackTrace();}}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)throws IOException, ServletException {//獲取訪問的IP地址String remoteAddr = request.getRemoteAddr();//System.out.println('===============' + remoteAddr);//如果allowList為空,則認(rèn)為沒做限制,不為空則檢查是否限制if(allowList.size() == 0 || allowList == null) {filterChain.doFilter(request, response);} else {Boolean flag = false; //訪問標(biāo)志,默認(rèn)為false,限制訪問//進(jìn)行逐個(gè)檢查for(String regex : allowList){if(remoteAddr.matches(regex)){//ip沒被限制,正常訪問filterChain.doFilter(request, response);flag = true; //置為true,表示不限制訪問break;}}if(!flag) {//ip被限制,跳到指定頁面request.getRequestDispatcher('WEB-INF/success/error.jsp').forward(request, response);}}}@Overridepublic void destroy() {System.out.println('過濾器IpFilter結(jié)束。');}/** * 對(duì)配置文件進(jìn)行初始化并校驗(yàn) * @author 歐陽 * @serialData 20180728 * @throws IOException */public void initConfig() throws IOException {//將文件轉(zhuǎn)化成流InputStream inputStream = IpFilter.class.getResourceAsStream('../config/ipConfig.properties');Properties properties = new Properties();//通過Properties對(duì)象實(shí)例加載流properties.load(inputStream);//獲取三種配置方式的值String allowIP = properties.getProperty('allowIP');String allowIPRange = properties.getProperty('allowIPRange');String allowIPWildcard = properties.getProperty('allowIPWildcard');//校驗(yàn),校驗(yàn)失敗后拋出異常if(!validate(allowIP, allowIPRange, allowIPWildcard)) {throw new RuntimeException('配置文件有錯(cuò),請檢查!');}/* * 將每一種配置方法放置到allowList中 *///將第一種配置方法放到allowList中if(null != allowIP && !''.equals(allowIP.trim())) {String[] allowIPs = allowIP.split(',|;');for(String ip : allowIPs) {allowList.add(ip);}}//將第二種配置方法放到allowList中if(null != allowIPRange && !''.equals(allowIPRange.trim())) {//先進(jìn)行每一段的分割String[] allowIPRanges = allowIPRange.split(',|;');if(allowIPRanges.length > 0) {//對(duì)每一段進(jìn)行遍歷for(String allowRanges : allowIPRanges) {if(allowRanges != null && !''.equals(allowRanges.trim())) {//對(duì)該段的ip進(jìn)行解析String[] ips = allowRanges.split('-');if(ips.length > 0 && ips.length < 3) {String from = ips[0];//得到該段的起始ipString to = ips[1]; //得到該段的結(jié)束ip//獲取該ip段地址的前三段,因?yàn)槠鹗己徒Y(jié)束的ip的前三段一樣String share = from.substring(0, from.lastIndexOf('.')+1);//獲取該ip段的起始ip的最后一段int start = Integer.parseInt(from.substring(from.lastIndexOf('.')+1, from.length()));//獲取該ip段的結(jié)束ip的最后一段int end = Integer.parseInt(to.substring(to.lastIndexOf('.')+1, to.length()));for(int i=start; i<=end; i++) {String ip = share + String.valueOf(i);allowList.add(ip);}} else {throw new RuntimeException('配置文件有錯(cuò),請檢查!');}}}}}//將第三種配置方法放到allowList中if(allowIPWildcard != null && !''.equals(allowIPWildcard)) {//獲取每個(gè)含通配符的ip地址String[] allowIPWildcards = allowIPWildcard.split(',|;');if(allowIPWildcards.length > 0) {for(String ip : allowIPWildcards) {if(ip.indexOf('*') != -1) {//對(duì)*進(jìn)行替換ip = ip.replaceAll('*', '(25[0-5]|2[0-4]d|[0-1]d{2}|[1-9]?d)');allowList.add(ip);} else {throw new RuntimeException('配置文件有錯(cuò),請檢查!');}}}}//打印輸出allowListfor(String str : allowList) {System.out.println(str);}}/** * 對(duì)配置文件進(jìn)行校驗(yàn) * @author ouyang * @serialData 20180728 * @param allowIP * @param allowIPRange * @param allowIPWildcard * @return */public Boolean validate(String allowIP, String allowIPRange, String allowIPWildcard) {Boolean result = false;//IP地址每一段的正則String regx = '(25[0-5]|2[0-4]d|[0-1]d{2}|[1-9]?d)';//整個(gè)ip的正則String ipRegx = regx + '.' + regx + '.'+ regx + '.' + regx;//對(duì)第一種方式進(jìn)行校驗(yàn)Pattern pattern = Pattern.compile('('+ipRegx+')|('+ipRegx+'(,|;))*');if(this.isNullorMatches(allowIP, pattern)){result = true; //匹配成功} else {result = false;}//對(duì)第二種方式進(jìn)行校驗(yàn)pattern = Pattern.compile('('+ipRegx+')-('+ipRegx+')|' + '(('+ipRegx+')-('+ipRegx+')(,|;))*');if(this.isNullorMatches(allowIPRange, pattern)){result = true; //匹配成功} else {result = false;}//對(duì)第三種方式進(jìn)行校驗(yàn)pattern = Pattern.compile('('+regx+'.'+ regx+'.'+regx+'.'+ '*)|' + '('+regx+'.'+regx+'.'+regx+'.'+ '*(,|;))*');if(this.isNullorMatches(allowIPWildcard, pattern)){result = true; //匹配成功} else {result = false;}return result;}/** * 進(jìn)行正則匹配 * @author 歐陽 * @serialData 20180728 * @param allow * @return */public Boolean isNullorMatches(String allow, Pattern pattern) {//如果為空,說明用戶沒添加該項(xiàng),不做處理if(allow == null || ''.equals(allow.trim())) {return true;} else {//在最后面沒有,或;的給添上if(!allow.endsWith(';') && !allow.endsWith(',')) {allow += ';';}//如果匹配,則返回trueif(pattern.matcher(allow).matches()) {return true;}}return false;}}
到此這篇關(guān)于詳解Java Web如何限制訪問的IP的兩種方法的文章就介紹到這了,更多相關(guān)Java 限制訪問的IP內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. msxml3.dll 錯(cuò)誤 800c0019 系統(tǒng)錯(cuò)誤:-2146697191解決方法2. ASP中實(shí)現(xiàn)字符部位類似.NET里String對(duì)象的PadLeft和PadRight函數(shù)3. jsp+servlet簡單實(shí)現(xiàn)上傳文件功能(保存目錄改進(jìn))4. 微信開發(fā) 網(wǎng)頁授權(quán)獲取用戶基本信息5. JavaWeb Servlet中url-pattern的使用6. asp批量添加修改刪除操作示例代碼7. 詳解瀏覽器的緩存機(jī)制8. XML入門的常見問題(一)9. HTML5 Canvas繪制圖形從入門到精通10. css代碼優(yōu)化的12個(gè)技巧
