web开发中出于安全方面的考虑,对于后台管理项目一般会对用户访问作限制,常见的作法是硬件上设置白名单,过滤掉不须要的IP访问来保证管理平台的安全。可是在硬件操做不方便的情形之下,就须要开发人员经过程序对访问的IP进行限制,具体的实现方式可能会受到实际环境的影响而稍有不一样,本文针对直接部署在tomcat下web项目(且无nginx或其余形式作代理)作一下详细说明。java
首先在web.xml中配置相应的参数,而后自定义一个filter实现Filter接口:在子定义的filter里面的init方法和doFilter方法进行处理。init方法中获取web.xml中配置的容许访问的IP白名单,并对其进行有效性验证及格式处理,定义为集合allow;doFilter方法中从请求中获取请求来源的IP地址,验证地址有效性,遍历集合allow,比较获取的来源IP是否在集合allow中存在,存在就放行,不存在response用数据流的形式返回“您的IP被限制访问!”信息给访问者,至此,IP限制部分介绍完毕。文中剩余内容是对请求路由的限制实现,也可供参考。nginx
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <filter> <filter-name>loginFilter</filter-name> <filter-class>com.bjdata.oldsite.LoginFilter</filter-class> <init-param> <param-name>AllowIPList</param-name> <param-value> 192.168.0.* ; 219.143.182.110 ; 192.168.20.140-192.168.20.205 </param-value> </init-param> </filter> <filter-mapping> <filter-name>loginFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
package com.bjdata.oldsite; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Pattern; /** * @Auther: * @Date: * @Description: */ public class LoginFilter implements Filter { // 容许的IP访问列表 private Set<String> ipList = new HashSet<String>(); // IP的正则 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 init(FilterConfig filterConfig) throws ServletException { // 从web.xml读取参数 String allowIp = filterConfig.getInitParameter("AllowIPList"); // 转换IP地址 init(allowIp); System.err.println("Allow IP list:" + ipList); } /** * 转换IP地址的形式 * @param allowIp */ private void init(String allowIp) { // 192.168.0.*转换为192.168.0.1-192.168.0.255 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<>(); 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]; } } StringBuilder fromIP = new StringBuilder(); StringBuilder endIP = new StringBuilder(); 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); } } } } /** * 在添加至白名单时进行格式校验 * @param allow * @return */ private boolean validate(String allow) { for (String s : allow.split("-")){ if (!pattern.matcher(s).matches()) { return false; } } return true; } /** * 对单个IP节点进行范围限定 * @param ip * @return 返回限定后的IP范围,格式为List[10;19, 100;199] */ private List<String> complete(String ip) { List<String> com = new ArrayList<>(); if (ip.length() == 1) { com.add("0;255"); }else if (ip.length() == 2) { String s1 = complete(ip, 1); if (s1 != null){ com.add(s1); } String s2 = complete(ip, 2); if (s2 != null) { com.add(s2); } }else { String s1 = complete(ip, 1); if (s1 != null) { com.add(s1); } } return com; } /** * 字符串格式处理 * @param ip * @param length * @return */ private String complete(String ip, int length) { String from = ""; String end = ""; if (length == 1) { from = ip.replace("*", "0"); end = ip.replace("*", "9"); }else{ from = ip.replace("*", "00"); end = ip.replace("*", "99"); } if (Integer.valueOf(from) > 255){ return null; } if (Integer.valueOf(end) > 255) { end = "255"; } return from + ";" + end; } }
package com.bjdata.oldsite; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Pattern; /** * @Auther: * @Date: * @Description: */ public class LoginFilter implements Filter { // 容许的IP访问列表 private Set<String> ipList = new HashSet<String>(); // IP的正则 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 doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)servletRequest; HttpServletResponse response = (HttpServletResponse)servletResponse; // 登陆IP控制 String ip = request.getRemoteAddr(); InetAddress inet = null; try { inet = InetAddress.getLocalHost(); if (ip.equals("127.0.0.1")){ ip = inet.getHostAddress(); } } catch (UnknownHostException e) { e.printStackTrace(); } if (!checkLoginIP(ip)) { response.getOutputStream().write(("您的IP被限制访问!").getBytes()); /*response.getOutputStream().write((ip + "ip forbidden.").getBytes());*/ response.getOutputStream().flush(); return; } // 登陆路由控制 String requestURI = request.getRequestURI(); System.out.println(requestURI); if(request.getRequestURI().indexOf("login.jsp")<0 && !requestURI.equals("/oldSite/getValidateCode.jsp")){ HttpSession session = request.getSession(); String sessionKey = (String)session.getAttribute("sessionKey"); if(sessionKey==null){ response.sendRedirect("login.jsp"); } } // 放行 filterChain.doFilter(request,response); } /** * 检查IP是不是容许的IP * @param ip * @return */ 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; break; } } if (check) { return true; } } } } return false; } }
package com.bjdata.oldsite; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Pattern; /** * @Auther: * @Date: * @Description: */ public class LoginFilter implements Filter { // 容许的IP访问列表 private Set<String> ipList = new HashSet<String>(); // IP的正则 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 init(FilterConfig filterConfig) throws ServletException { // 从web.xml读取参数 String allowIp = filterConfig.getInitParameter("AllowIPList"); // 转换IP地址 init(allowIp); System.err.println("Allow IP list:" + ipList); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)servletRequest; HttpServletResponse response = (HttpServletResponse)servletResponse; // 登陆IP控制 String ip = request.getRemoteAddr(); InetAddress inet = null; try { inet = InetAddress.getLocalHost(); if (ip.equals("127.0.0.1")){ ip = inet.getHostAddress(); } } catch (UnknownHostException e) { e.printStackTrace(); } if (!checkLoginIP(ip)) { response.getOutputStream().write(("您的IP被限制访问!").getBytes()); /*response.getOutputStream().write((ip + "ip forbidden.").getBytes());*/ response.getOutputStream().flush(); return; } // 登陆路由控制 String requestURI = request.getRequestURI(); System.out.println(requestURI); if(request.getRequestURI().indexOf("login.jsp")<0 && !requestURI.equals("/oldSite/getValidateCode.jsp")){ HttpSession session = request.getSession(); String sessionKey = (String)session.getAttribute("sessionKey"); if(sessionKey==null){ response.sendRedirect("login.jsp"); } } // 放行 filterChain.doFilter(request,response); } @Override public void destroy() { } /** * 转换IP地址的形式 * @param allowIp */ private void init(String allowIp) { // 192.168.0.*转换为192.168.0.1-192.168.0.255 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<>(); 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]; } } StringBuilder fromIP = new StringBuilder(); StringBuilder endIP = new StringBuilder(); 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); } } } } /** * 在添加至白名单时进行格式校验 * @param allow * @return */ private boolean validate(String allow) { for (String s : allow.split("-")){ if (!pattern.matcher(s).matches()) { return false; } } return true; } /** * 对单个IP节点进行范围限定 * @param ip * @return 返回限定后的IP范围,格式为List[10;19, 100;199] */ private List<String> complete(String ip) { List<String> com = new ArrayList<>(); if (ip.length() == 1) { com.add("0;255"); }else if (ip.length() == 2) { String s1 = complete(ip, 1); if (s1 != null){ com.add(s1); } String s2 = complete(ip, 2); if (s2 != null) { com.add(s2); } }else { String s1 = complete(ip, 1); if (s1 != null) { com.add(s1); } } return com; } /** * 字符串格式处理 * @param ip * @param length * @return */ private String complete(String ip, int length) { String from = ""; String end = ""; if (length == 1) { from = ip.replace("*", "0"); end = ip.replace("*", "9"); }else{ from = ip.replace("*", "00"); end = ip.replace("*", "99"); } if (Integer.valueOf(from) > 255){ return null; } if (Integer.valueOf(end) > 255) { end = "255"; } return from + ";" + end; } /** * 检查IP是不是容许的IP * @param ip * @return */ 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; break; } } if (check) { return true; } } } } return false; } }