VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Java教程 >
  • Spring Boot 防止接口被恶意刷新、暴力请求

​在实际项目使用中,必须要考虑服务的安全性,当服务部署到互联网以后,就要考虑服务被恶意请求和暴力攻击的情况,下面的教程,通过Spring Boot提供的HandlerInterceptor和Redis 针对 Url + ip在一定时间内访问的次数来将ip禁用,可以根据自己的业务需求进行相应的修改,以达到自己的目的。

首先创建一个自定义的拦截器类,也是最核心的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/**
 * @ProjectName: cdkj-framework
 * @Package: com.cdkjframework.core.spring.filter
 * @ClassName: FilterHandlerInterceptor
 * @Description: 拦截过滤
 * @Author: xiaLin
 * @Date: 2022/6/22 13:36
 * @Version: 1.0
 */
public class FilterHandlerInterceptor implements HandlerInterceptor {
 
  /**
   * 日志
   */
  private LogUtils logUtils = LogUtils.getLogger(FilterHandlerInterceptor.class);
 
  /**
   * redis锁
   */
  private final RedisLettuceLock redisLettuceLock;
 
  /**
   * IP头部变量(可能通过Nginx代理后)
   */
  private static final String HEADER_IP = "X-Real-IP";
 
  /**
   * 锁IP请求URL地址KEY
   */
  private static final String LOCK_IP_URL_KEY = "lock_ip_";
 
  /**
   * IP请求URL地址时间
   */
  private static final String IP_URL_REQ_TIME = "ip_url_times_";
 
  /**
   * 极限时间
   */
  private static final long LIMIT_TIMES = 5;
 
  /**
   * IP锁定时间 秒
   */
  private static final int IP_LOCK_TIME = 60;
 
  /**
   * 构建函数
   */
  public FilterHandlerInterceptor(RedisLettuceLock redisLettuceLock) {
    this.redisLettuceLock = redisLettuceLock;
  }
 
  /**
   * 预处理
   *
   * @param request  请求
   * @param response 响应
   * @param o        参数
   * @return 返回结果
   * @throws Exception 异常信息
   */
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
    String ip = request.getHeader(HEADER_IP);
    if (StringUtils.isNullAndSpaceOrEmpty(ip)) {
      ip = request.getRemoteAddr();
    }
    logUtils.info("request 请求地址 Uri={},ip={}", request.getRequestURI(), ip);
    if (ipIsLock(ip)) {
      logUtils.info("ip访问被禁止={}", ip);
      ResponseBuilder builder = ResponseBuilder.failBuilder("ip访问被禁止");
      returnJson(response, builder);
      return false;
    }
    if (!addRequest(ip, request.getRequestURI())) {
      ResponseBuilder builder = ResponseBuilder.failBuilder("ip访问被禁止");
      returnJson(response, builder);
      return false;
    }
    return true;
  }
 
  @Override
  public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
 
  }
 
  @Override
  public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
 
  }
 
  /**
   * IP 是否已锁
   *
   * @param ip IP 地址
   * @return 返回是否成功
   */
  private Boolean ipIsLock(String ip) {
    if (redisLettuceLock.lock(LOCK_IP_URL_KEY + ip)) {
      return true;
    }
    return false;
  }
 
  /**
   * 添加请求信息
   *
   * @param ip  IP 地址
   * @param uri 请求路径
   * @return 返回是否成功
   */
  private Boolean addRequest(String ip, String uri) {
    String key = IP_URL_REQ_TIME + ip + uri;
    if (RedisUtils.syncExists(key)) {
      long time = RedisUtils.syncIncr(key, IntegerConsts.ONE);
      if (time >= LIMIT_TIMES) {
        redisLettuceLock.lock(LOCK_IP_URL_KEY + ip, IP_LOCK_TIME, ip);
        return false;
      }
    else {
      redisLettuceLock.lock(key, (long) IntegerConsts.ONE, IntegerConsts.ONE);
    }
    return true;
  }
 
  /**
   * 返回结果
   *
   * @param response 响应
   * @param builder  返回结果
   * @throws Exception 异常信息
   */
  private void returnJson(HttpServletResponse response, ResponseBuilder builder) throws Exception {
    ResponseUtils.out(response, builder);
  }
}

  最后将上面自定义的拦截器通过WebMvcConfigurer下的registry.addInterceptor添加一下,就生效了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
 * @ProjectName: cdkj-framework
 * @Package: com.cdkjframework.core.spring.filter
 * @ClassName: WebMvcFilterConfigurerAdapter
 * @Description: java类作用描述
 * @Author: xiaLin
 * @Date: 2022/6/22 13:37
 * @Version: 1.0
 */
@RequiredArgsConstructor
public class WebMvcFilterConfigurerAdapter implements WebMvcConfigurer {
 
    /**
     * redis锁
     */
    private final RedisLettuceLock redisLettuceLock;
 
    /**
     * 过虑句柄拦截器
     *
     * @return 返回拦截器
     */
    @Bean
    private FilterHandlerInterceptor filterHandlerInterceptor() {
        return new FilterHandlerInterceptor(redisLettuceLock);
    }
 
    /**
     * 添加 拦截器
     *
     * @param registry 拦截器注册
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(filterHandlerInterceptor()).addPathPatterns("/**");
    }
}

  自己可以写一个for循环来测试改功能,这里就不具体详细介绍了。

文章中的工具类可参考:https://gitee.com/cdkjframework/common/tree/1.0.2/

出处:https://www.cnblogs.com/cdkj/p/17134389.html
 


相关教程