给大家分享个过滤IP的Filter

iamrf 2011-12-02 04:54:55
最近刚写了个用于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*,即*右边不能有数字,只能支持一个*号

以下是代码:

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-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列表的代码即可。
...全文
672 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
qcj1125 2011-12-06
  • 打赏
  • 举报
回复
还可以.
nodream521 2011-12-06
  • 打赏
  • 举报
回复
很好,收了
iamrf 2011-12-05
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 heyukun 的回复:]

楼主 这个配置有点问题
<filter>
<filter-name>requestAllowFilter</filter-name>
<filter-class>com.jm.kefu.Filter.LoginIPFilter</filter-class>
<init-param>
<param-name>RedirectURL</param-name>
<param-value>/……
[/Quote]

你没有配置<param-name>ProtectedURLList</param-name>,这个得需要同时配置受保护列表和IP访问列表才能起效。

详细请看代码中checkRequestURL()方法的实现,这个方法是用来过滤URL的,可以根据你自己的业务需求更改这个方法的实现。
heyukun 2011-12-05
  • 打赏
  • 举报
回复
楼主 这个配置有点问题
<filter>
<filter-name>requestAllowFilter</filter-name>
<filter-class>com.jm.kefu.Filter.LoginIPFilter</filter-class>
<init-param>
<param-name>RedirectURL</param-name>
<param-value>/noRight.jsp</param-value>
</init-param>
<init-param>
<param-name>AllowIPList</param-name>
<param-value>
180.111.28.193 ;
192.168.0.* ;
192.168.2.140-192.168.2.155
</param-value>
</init-param>
<filter-mapping>
<filter-name>requestAllowFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
</filter>
iamrf 2011-12-05
  • 打赏
  • 举报
回复
自己顶一下,挺好的功能,不能沉了啊~~
Cactus_hxk 2011-12-02
  • 打赏
  • 举报
回复
非常不错!刚好有个项目,需要用,谢谢了楼主
qdcaijunjun 2011-12-02
  • 打赏
  • 举报
回复
先收着,以后有机会再用
easonwang14 2011-12-02
  • 打赏
  • 举报
回复
楼主好人呐.....这个类收着.以后肯定有用的
iamrf 2011-12-02
  • 打赏
  • 举报
回复
补充一下,由于各个MVC框架请求是的URL会有些细微差异,请根据实际情况修改获取URL部分的代码和checkRequestURL()方法,以便适用于实际情况。

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧