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

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

1.配置拦截器

这里使用全局拦截:

<mvc:interceptors>
   <mvc:interceptor>
     <mvc:mapping path="/**"/>
     <bean class="com.nps.base.filter.LoginInterceptor"></bean>
   </mvc:interceptor>
</mvc:interceptors>

拦截器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<String, String> 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<String, String> getParameterMap(HttpServletRequest request) {
 Enumeration<String> names = request.getParameterNames();
 String name;
 Map<String, String> map = new HashMap<String, String>();
 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<String, String> 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<String,String> readAllProperties() throws FileNotFoundException,IOException {
    //保存所有的键值
    Map<String,String> map=new HashMap<String,String>();
    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秒就会重新读取配置文件缓存其实更好,不使用缓存主要是为了,因为放在缓存中还要写对应的操作方法,如果有什么更好的方法欢迎大家讨论。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • spring boot拦截器实现IP黑名单实例代码

    前言 最近一直在搞 Hexo+GithubPage 搭建个人博客,所以没怎么进行 SpringBoot 的学习.所以今天就将上次的"?秒防刷新"进行了一番修改.上次是采用注解加拦截器(@Aspect)来实现功能的.但是,如果需求是一个全局的拦截器对于大部分URL都进行拦截的话,自己一个个加显然是不可能的.而且上次的拦截器对于Controller的参数有所要求,在实际他人引用总是显得不方便.所以,这次使用了继承HandlerInterceptor来实现拦截器. 功能需求 对于项目中某类U

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

    以前没有遇到这个需要,后面在网上找了很久,参考了很多文档给出的方案. 1.配置拦截器 这里使用全局拦截: <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.nps.base.filter.LoginInterceptor"></bean> </mvc:interceptor> </

  • Spring boot拦截器实现IP黑名单的完整步骤

    一·业务场景和需要实现的功能 以redis作为IP存储地址实现. 业务场景:针对秒杀活动或者常规电商业务场景等,防止恶意脚本不停的刷接口. 实现功能:写一个拦截器拦截掉黑名单IP,额外增加一个接口,将ip地址添加到redis中,并且返回redis中当前全部ip 二·Springboot中定义一个拦截器 @Order(0) @Aspect @Component public class AopInterceptor { /** * 定义拦截器规则 */ @Pointcut("execution(*

  • 浅谈SpringMVC的拦截器(Interceptor)和Servlet 的过滤器(Filter)的区别与联系 及SpringMVC 的配置文件

    1.过滤器: 依赖于servlet容器.在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次.使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据. 比如:在过滤器中修改字符编码:在过滤器中修改 HttpServletRequest的一些参数,包括:过滤低俗文字.危险字符等 关于过滤器的一些用法可以参考我写过的这些文章: 继承HttpServletRequestWrapper以实现在Filter中修改HttpServletRequest的参

  • SpringMVC自定义拦截器登录检测功能的实现代码

    目录 一.定义登录控制器 二.自定义登录拦截器 一.定义登录控制器 目录结构 代码: 1.创建TUser类 package com.demo.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class TUser { private String name;

  • 详解SpringMVC HandlerInterceptor拦截器的使用与参数

    目录 拦截器概念: 拦截器VS过滤器 自定义拦截器开发过程: 拦截器配置项: 多拦截器配置: 拦截器概念: 拦截器( Interceptor)是一种动态拦截方法调用的机制,请求处理过程解析 核心原理: AOP思想 拦截器链:多个拦截器按照一定的顺序,对原始被调用功能进行增强 作用: 在指定的方法调用前后执行预先设定后的的代码 阻止原始方法的执行 拦截器VS过滤器 归属不同: 过滤器属于Servlet技术, 拦截器属于SpringMVC技术拦截内容不同: 过滤器对所有访问进行增强, 拦截器仅针对S

  • java SpringMvc中拦截器的应用

    目录 什么是拦截器 基本使用 实例 总结 什么是拦截器 拦截器(Interceptor)是SpringMVC中的组件.可以使很多个请求被处理时,都会执行拦截器中的代码.拦截器可以选择阻止执行或放行. 举个栗子: 基本使用 在SpringMVC中实现HandlerInteceptor拦截器接口,这个类就是一个拦截器类. 利用拦截器最核心的在用控制preHandle方法的返回值,返回true就成功了,返回false就表示进行拦截处理了. 实例 首先,创建一个类继承拦截器 public class D

  • SpringMVC中拦截器的实现

    SpringMVC 中的 Interceptor 拦截器是非常重要和相当有用的,它的主要作用是拦截指定的用户请求,并进行相应的预处理与后处理.其拦截的时间点在“处理器映射器根据用户提交的请求映射出了所要执行的处理器类,并且也找到了要执行该处理器类的处理器适配器,在处理器适配器执行处理器之前”.当然,在处理器映射器映射出所要执行的处理器类时,已经将拦截器与处理器组合为了一个处理器执行链,并返回给了中央调度器. 拦截器和过滤器很像,但是又有比较大的区别 过滤器是servlet规范的一部分,任何jav

  • 详解SpringMVC的拦截器参数及拦截器链配置

    目录 一.拦截器参数 二.拦截器链配置 一.拦截器参数 前置处理 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle..."); return true; } 参数: ■ request:请求对象 ■ response:响应对象 ■ handle

  • 详解SpringMVC中拦截器的概念及入门案例

    目录 一.拦截器概念 二.拦截器入门案例 一.拦截器概念 拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行 作用: 在指定的方法调用前后执行预先设定的代码 阻止原始方法的执行 拦截器与过滤器区别  归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术 拦截内容不同:Filter对所有的访问进行增强,Interceptor仅针对SpringMVC的访问进行增强 二.拦截器入门案例 1.声明拦截器的

随机推荐