用于过滤IP的Filter
2012-02-07 12:41
351 查看
最近刚写了个用于IP过滤的Filter,支持对需要保护的URL列表进行指定IP段用户访问。
支持IP段*通配符配置,如:* --所有IP;192.168.* --所有192.168.开头的IP;192.168.0.* --所有0网段的IP;10.195.13.0-10.195.13.255 --也支持这种格式的IP段指定; 192.168.1.100 --单独IP指定;192.168.1*.50 --所有以192.168.1开头.50结尾的IP,即192.168.10.50-192.168.19.50; 192.168.100.50-192.168.199.50。
暂不支持如这种格式的指定:192.168.1*5.10、192.168.*5.10、192.168.*.2*,即*右边不能有数字,只能支持一个*号
以下是代码:
相关配置:
比如 “/mail/sendMail.do” 这个URL 只能够在允许的访问IP列表中的用户才能够访问,则需要在web.xml中这样配置
<param-value> 192.168.0.* ; 9.193.10.54 ; 192.168.2.140-192.168.2.155 </param-value> </init-param></filter>
<param-name>ProtectedURLList</param-name>中配置需要进行控制的URL访问列表;
<param-name>AllowIPList</param-name>中配置允许的IP列表;
<param-name>RedirectURL</param-name>中配置如果出发了访问权限,重定向至哪个地方。
如果不配ProtectedURLList,则所有访问都不受限制,即使配置了IP白名单;
如果配置AllowIPList,并同时配置了ProtectedURLList,才会起到控制作用。
优先判断IP白名单,再去判断URL控制列表。
如果只需要IP控制逻辑,修改下过滤URL列表的代码即可。
支持IP段*通配符配置,如:* --所有IP;192.168.* --所有192.168.开头的IP;192.168.0.* --所有0网段的IP;10.195.13.0-10.195.13.255 --也支持这种格式的IP段指定; 192.168.1.100 --单独IP指定;192.168.1*.50 --所有以192.168.1开头.50结尾的IP,即192.168.10.50-192.168.19.50; 192.168.100.50-192.168.199.50。
暂不支持如这种格式的指定:192.168.1*5.10、192.168.*5.10、192.168.*.2*,即*右边不能有数字,只能支持一个*号
以下是代码:
import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; 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; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; /** * 该过滤器用于过滤非指定列表中的IP不能访问指定功能权限。 * * @author <a href="mailto:luzhich@cn.ibm.com">Lucas</a> * * @version 1.0 2011-11-29 */ public class LoginIPFilter implements Filter { protected Logger log = Logger.getLogger(LoginIPFilter.class); // 当访问IP违规时重定向至哪个URL private String redirectURL = null; // 允许的IP访问列表 private Set<String> ipList = new HashSet<String>(); // 不在IP访问列表中的访问者不允许访问的URL列表 private List<String> protectedURL = new ArrayList<String>(); private Pattern pattern = Pattern .compile("(1\\d{1,2}|2[0-4]\\d|25[0-5]|\\d{1,2})\\." + "(1\\d{1,2}|2[0-4]\\d|25[0-5]|\\d{1,2})\\." + "(1\\d{1,2}|2[0-4]\\d|25[0-5]|\\d{1,2})\\." + "(1\\d{1,2}|2[0-4]\\d|25[0-5]|\\d{1,2})"); @Override public void destroy() { } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) arg0; HttpServletResponse response = (HttpServletResponse) arg1; // 获取请求IP InetAddress inet = null; String ip = request.getRemoteAddr(); try { inet = InetAddress.getLocalHost(); if (ip.equals("127.0.0.1")) ip = inet.getHostAddress(); } catch (UnknownHostException e) { e.printStackTrace(); } // 获取请求URL String reurl = request.getRequestURI(); String query = request.getQueryString(); if (query != null && !"".equals(query)) reurl += query; if (reurl.indexOf("/WebMail/") > -1) reurl = reurl.replaceFirst("/WebMail/", ""); if (reurl.indexOf("&") > -1) reurl = reurl.substring(0, reurl.indexOf("&")); // 对访问的IP进行过滤和URL白名单进行交叉匹配 // 不在IP白名单里 if (!checkLoginIP(ip)) { // 并且访问URL在控制列表里,跳转 if (checkRequestURL(reurl)) { log.warn("Receive a request which is request IP " + "without allowIPList, and requested " + "a protected URL. detail:" + ip + ", request URL:" + reurl); response.sendRedirect(request.getContextPath() + redirectURL); return; } } chain.doFilter(arg0, arg1); } @Override public void init(FilterConfig arg0) throws ServletException { redirectURL = arg0.getInitParameter("RedirectURL"); String url = arg0.getInitParameter("ProtectedURLList"); protectedURL = Arrays.asList(url.split(";")); String allowIp = arg0.getInitParameter("AllowIPList"); init(allowIp); log.info("Allow IP list:" + ipList); log.info("Protected URL:" + protectedURL); } private void init(String allowIp) { for (String allow : allowIp.replaceAll("\\s", "").split(";")) { if (allow.indexOf("*") > -1) { String[] ips = allow.split("\\."); String[] from = new String[] { "0", "0", "0", "0" }; String[] end = new String[] { "255", "255", "255", "255" }; List<String> tem = new ArrayList<String>(); for (int i = 0; i < ips.length; i++) if (ips[i].indexOf("*") > -1) { tem = complete(ips[i]); from[i] = null; end[i] = null; } else { from[i] = ips[i]; end[i] = ips[i]; } StringBuffer fromIP = new StringBuffer(); StringBuffer endIP = new StringBuffer(); for (int i = 0; i < 4; i++) if (from[i] != null) { fromIP.append(from[i]).append("."); endIP.append(end[i]).append("."); } else { fromIP.append("[*]."); endIP.append("[*]."); } fromIP.deleteCharAt(fromIP.length() - 1); endIP.deleteCharAt(endIP.length() - 1); for (String s : tem) { String ip = fromIP.toString().replace("[*]", s.split(";")[0]) + "-" + endIP.toString().replace("[*]", s.split(";")[1]); if (validate(ip)) ipList.add(ip); } } else { if (validate(allow)) ipList.add(allow); } } } /** * 对单个IP节点进行范围限定 * * @param arg * @return 返回限定后的IP范围,格式为List[10;19, 100;199] */ private List<String> complete(String arg) { List<String> com = new ArrayList<String>(); if (arg.length() == 1) { com.add("0;255"); } else if (arg.length() == 2) { String s1 = complete(arg, 1); if (s1 != null) com.add(s1); String s2 = complete(arg, 2); if (s2 != null) com.add(s2); } else { String s1 = complete(arg, 1); if (s1 != null) com.add(s1); } return com; } private String complete(String arg, int length) { String from = ""; String end = ""; if (length == 1) { from = arg.replace("*", "0"); end = arg.replace("*", "9"); } else { from = arg.replace("*", "00"); end = arg.replace("*", "99"); } if (Integer.valueOf(from) > 255) return null; if (Integer.valueOf(end) > 255) end = "255"; return from + ";" + end; } /** * 在添加至白名单时进行格式校验 * * @param ip * @return */ private boolean validate(String ip) { for (String s : ip.split("-")) if (!pattern.matcher(s).matches()) { return false; } return true; } private boolean checkRequestURL(String url) { if (protectedURL.isEmpty()) return false; for (String allow : protectedURL) { if (allow.indexOf(url) > -1) { return true; } } return false; } private boolean checkLoginIP(String ip) { if (ipList.isEmpty() || ipList.contains(ip)) return true; else { for (String allow : ipList) { if (allow.indexOf("-") > -1) { String[] from = allow.split("-")[0].split("\\."); String[] end = allow.split("-")[1].split("\\."); String[] tag = ip.split("\\."); // 对IP从左到右进行逐段匹配 boolean check = true; for (int i = 0; i < 4; i++) { int s = Integer.valueOf(from[i]); int t = Integer.valueOf(tag[i]); int e = Integer.valueOf(end[i]); if (!(s <= t && t <= e)) check = false; } if (check) return true; } } } return false; } }
相关配置:
比如 “/mail/sendMail.do” 这个URL 只能够在允许的访问IP列表中的用户才能够访问,则需要在web.xml中这样配置
<filter> <filter-name>requestAllowFilter</filter-name> <filter-class>cn.mycode.filter.LoginIPFilter</filter-class> <init-param> <param-name>RedirectURL</param-name> <param-value>/index.jsp</param-value> </init-param> <init-param> <param-name>ProtectedURLList</param-name> <param-value>mail/addUser;</param-value> </init-param> <init-param><param-name>AllowIPList</param-name>
<param-value> 192.168.0.* ; 9.193.10.54 ; 192.168.2.140-192.168.2.155 </param-value> </init-param></filter>
<param-name>ProtectedURLList</param-name>中配置需要进行控制的URL访问列表;
<param-name>AllowIPList</param-name>中配置允许的IP列表;
<param-name>RedirectURL</param-name>中配置如果出发了访问权限,重定向至哪个地方。
如果不配ProtectedURLList,则所有访问都不受限制,即使配置了IP白名单;
如果配置AllowIPList,并同时配置了ProtectedURLList,才会起到控制作用。
优先判断IP白名单,再去判断URL控制列表。
如果只需要IP控制逻辑,修改下过滤URL列表的代码即可。
相关文章推荐
- 基于Filter-Hook Driver(使用ipfirewall.h)的IP过滤驱动
- JavaWeb-过滤器Filter学习(三)实现用户的自动登录与IP黑名单过滤
- Python 内建的filter()函数用于过滤序列。
- filter_var过滤私有ip
- Solaris配置ipfilter
- Java for Web学习笔记(四二):Filter(4)用于压缩
- tomcat使用filter,log4j过滤生成日志
- nginx图片过滤处理模块http_image_filter_module
- Scala 容器基础(十七):使用filter方法过滤集合元素
- 用TCP/IP过滤保护您的计算机
- Spark的Dataset操作(二)-过滤的filter和where
- 用于过滤空白字符的几种常见的js正则表达式pattern
- [导入]用TCP/IP 网络连接过滤保护用户计算机
- fail2ban帮助postfix过滤恶意IP
- 为ZooKeeper增加一个小功能:指定IP进行受限客户端过滤
- 自己做项目时整理的一些用于过滤的正则表达式
- struts2 使filter 过滤某些路径
- Filter Manager Concepts 过滤管理器思想
- C# 验证过滤代理IP是否有效
- 过滤查询filter angularjs