JAVA通过拦截器实现IP黑名单

SpringMVC:通过拦截器实现IP黑名单

以前没有遇到这个需要,后面在网上找了很久,参考了很多文档给出的方案。

1.配置拦截器

这里使用全局拦截:

 
     
         
          
     
  

拦截器LoginInterceptor代码:

package com.nps.base.filter;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.nps.utils.IpInterceptUtils;

  /**
  * 验证拦截器
  * @author HUANG
 */
public class LoginInterceptor implements HandlerInterceptor {
private final static Logger logger = LoggerFactory
		.getLogger(LoginInterceptor.class);

@Override
public void afterCompletion(HttpServletRequest arg0,
		HttpServletResponse arg1, Object arg2, Exception arg3)
		throws Exception {

}

@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
		Object arg2, ModelAndView arg3) throws Exception {

}

@Override
public boolean preHandle(HttpServletRequest request,
		HttpServletResponse response, Object handler) throws Exception {
	String ip = getIpAddress(request);
	if (IpInterceptUtils.chickIpBreak(ip)) {
		return false;
	}
	Map map = getParameterMap(request);// 获取url中的所有参数
	String servletUrl = request.getServletPath();// servlet地址
	String url = getRealUrl(servletUrl, map);

	if (url.indexOf("/user/") == 0) {
		Object user = request.getSession().getAttribute("User");
		if (user == null) {
			// System.out.println("尚未登录,调到登录页面");
			response.sendRedirect(request.getContextPath() + "/loginOut.do");
			return false;
		}
	}

	return true;
}

/**
 * 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址;
 * 
 * @param request
 * @return
 * @throws IOException
 */
public final static String getIpAddress(HttpServletRequest request)
		throws IOException {
	// 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址

	String ip = request.getHeader("X-Forwarded-For");
	// if (logger.isInfoEnabled()) {
	// logger.info("getIpAddress(HttpServletRequest) - X-Forwarded-For - String ip="
	// + ip);
	// }

	if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
		if (ip == null || ip.length() == 0
				|| "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
			// if (logger.isInfoEnabled()) {
			// logger.info("getIpAddress(HttpServletRequest) - Proxy-Client-IP - String ip="
			// + ip);
			// }
		}
		if (ip == null || ip.length() == 0
				|| "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
			// if (logger.isInfoEnabled()) {
			// logger.info("getIpAddress(HttpServletRequest) - WL-Proxy-Client-IP - String ip="
			// + ip);
			// }
		}
		if (ip == null || ip.length() == 0
				|| "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
			// if (logger.isInfoEnabled()) {
			// logger.info("getIpAddress(HttpServletRequest) - HTTP_CLIENT_IP - String ip="
			// + ip);
			// }
		}
		if (ip == null || ip.length() == 0
				|| "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
			// if (logger.isInfoEnabled()) {
			// logger.info("getIpAddress(HttpServletRequest) - HTTP_X_FORWARDED_FOR - String ip="
			// + ip);
			// }
		}
		if (ip == null || ip.length() == 0
				|| "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
			// if (logger.isInfoEnabled()) {
			// logger.info("getIpAddress(HttpServletRequest) - getRemoteAddr - String ip="
			// + ip);
			// }
		}
	} else if (ip.length() > 15) {
		String[] ips = ip.split(",");
		for (int index = 0; index < ips.length; index++) {
			String strIp = (String) ips[index];
			if (!("unknown".equalsIgnoreCase(strIp))) {
				ip = strIp;
				break;
			}
		}
	}

	return ip;
}

/**
 * 根据request获取所有的参数集
 * 
 * @param request
 * @return
 */
protected Map getParameterMap(HttpServletRequest request) {
	Enumeration names = request.getParameterNames();
	String name;
	Map map = new HashMap();
	while (names.hasMoreElements()) {
		name = names.nextElement();
		map.put(name, request.getParameter(name).trim().replaceAll("'", ""));
	}
	return map;
}

/**
 * 获取url
 * 
 * @param uri
 * @param params
 * @return
 */
String getRealUrl(String uri, Map params) {
	StringBuffer sb = new StringBuffer(uri);
	if (params != null) {
		int i = 0;
		for (String key : params.keySet()) {
			i++;
			if (i == 1) {
				sb.append("?" + key + "=" + params.get(key));
			} else {
				sb.append("&" + key + "=" + params.get(key));
			}
		}
	}
	return sb.toString();
}
}

2.校验IP工具

public class IpInterceptUtils {
private static String date ;
private static PropertiesUtil p=null;
 /***
	  * 校验IP是否加入黑名单
	  * @param ip
	  * @return true 是在黑名单 
	  * @throws IOException
	  */
	 public static boolean chickIpBreak(String ip) throws IOException{
		 	if(p == null){
		 		 p = new PropertiesUtil("conf/ip-black.properties");
		 	}else{
		 		 String str = new SimpleDateFormat("MMddHHmmss").format(new Date());  
				 str=str.substring(0,9);
				 if(date==null || !date.equals(str)){  
					 date = str; 
					 p = new PropertiesUtil("conf/ip-black.properties");
				 }
		 	}
	        Enumeration en = p.getProps().propertyNames();
	        while (en.hasMoreElements()) {
	            String key = (String) en.nextElement();
	            if(key.equals(ip)){
	            	  return true;
	            }
	        }
			return false;
	 }
}

3.配置文件读取类

PropertiesUtil

package com.nps.base.model;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.springframework.stereotype.Component;

/**
 * 读取Properties综合类,默认绑定到classpath下的config.properties文件。
 * @author 
 */
@Component("PropertiesUtil")
public class PropertiesUtil {
    //配置文件的路径
    private String configPath=null;
    
    /**
     * 配置文件对象
     */
    private Properties props=null;
    
    /**
     * 默认构造函数,用于sh运行,自动找到classpath下的config.properties。
     */
    public PropertiesUtil() throws IOException{
    	if(props==null){
    		 InputStream in = PropertiesUtil.class.getClassLoader().getResourceAsStream("conf/application.properties");
    	     props = new Properties();
    	     props.load(in);
    	        //关闭资源
    	     in.close();
    	}
       
    }
    
    /**
     * 默认构造函数,用于sh运行,自动找到classpath下的config.properties。
     */
    public PropertiesUtil(String path) throws IOException{
    	if(props==null){
    		 InputStream in = PropertiesUtil.class.getClassLoader().getResourceAsStream(path);
    	     props = new Properties();
    	     props.load(in);
    	        //关闭资源
    	     in.close();
    	}
       
    }
    
    /**
     * 根据key值读取配置的值
     * Jun 26, 2010 9:15:43 PM
     * @author 朱志杰
     * @param key key值
     * @return key 键对应的值 
     * @throws IOException 
     */
    public String readValue(String key) throws IOException {
        return  props.getProperty(key);
    }
    
    /**
     * 读取properties的全部信息
     * @throws FileNotFoundException 配置文件没有找到
     * @throws IOException 关闭资源文件,或者加载配置文件错误
     * 
     */
    public Map readAllProperties() throws FileNotFoundException,IOException  {
        //保存所有的键值
        Map map=new HashMap();
        Enumeration en = props.propertyNames();
        while (en.hasMoreElements()) {
            String key = (String) en.nextElement();
            String Property = props.getProperty(key);
            map.put(key, Property);
        }
        return map;
    }

    /**
     * 设置某个key的值,并保存至文件。
     * @param key key值
     * @return key 键对应的值 
     * @throws IOException 
     */
    public void setValue(String key,String value) throws IOException {
        Properties prop = new Properties();
        InputStream fis = new FileInputStream(this.configPath);
        // 从输入流中读取属性列表(键和元素对)
        prop.load(fis);
        // 调用 Hashtable 的方法 put。使用 getProperty 方法提供并行性。
        // 强制要求为属性的键和值使用字符串。返回值是 Hashtable 调用 put 的结果。
        OutputStream fos = new FileOutputStream(this.configPath);
        prop.setProperty(key, value);
        // 以适合使用 load 方法加载到 Properties 表中的格式,
        // 将此 Properties 表中的属性列表(键和元素对)写入输出流
        prop.store(fos,"last update");
        //关闭文件
        fis.close();
        fos.close();
    }
    
    /**
	 * @return the props
	 */
	public Properties getProps() {
		return props;
	}

	public static void main(String[] args) {
        PropertiesUtil p;
        try {
            p = new PropertiesUtil("conf/ip-black.properties");
            Enumeration en = p.props.propertyNames();
            String str="";
            while (en.hasMoreElements()) {
                String key = (String) en.nextElement();
                System.out.println(key);
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

	
}

附上黑名单IP文件格式

ip-black.properties 配置文件

45.119.99.35
103.253.2.165
157.65.166.51
202.57.55.242
119.82.252.122
140.227.53.126
140.227.211.20
140.227.208.20
116.253.84.183

附加

之所以使用配置文件读取黑名单IP是为了加快数据读取速度,因为每次访问服务器都会被校验,使用数据库会加大数据库的压力,这个方法中每10秒就会重新读取配置文件缓存其实更好,不使用缓存主要是为了,因为放在缓存中还要写对应的操作方法,如果有什么更好的方法欢迎大家讨论

你可能感兴趣的:(java)