限制接口访问频率(拉黑用户)

文章目录


前言

在日常开发当中,遇到其他恶意攻击,恶意调用我们公共开放的接口,例如: 恶意调用短信接口,数以万计的请求,打到我们的公共短信服务,占用系统资源,其他用户无法完成其他业务操作。最终导致系统崩溃。

前些天提供了阿里的Canal组件的使用,今天就配合Canal组件,完成自定义请求拦截

一、解决方案

1:拦截器的原理

1:preHandle:在执行Handler之前(执行业务逻辑之前),根据拦截器链顺序执行;

2:postHandle:在执行Handler成功(执行业务逻辑成功)之后,根据拦截器链倒序执行,如果前面的流程中抛出异常或者请求被拦截则不会执行!

3:afterCompletion:在请求处理完毕之后执行,无论是否有响应视图,无论有没有通过preHandle,无论有没有抛出异常。只会对此前放行成功(preHandle返回true)的拦截器进行倒序调用

本质也就是一种AOP思想的实现,源码分析(后续)

2:自定义拦截注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE ,ElementType.METHOD})
@Inherited // 增强继承性
@Documented  
@Order(Ordered.HIGHEST_PRECEDENCE) // 设置优先级
public @interface RequestIntercept {

    /* 次数*/
    int count() default Integer.MAX_VALUE;

    /* 默认时间: 1分钟*/
    long time() default 60000;
}

二、使用步骤

1:自定义拦截器

@Component
@Slf4j
public class RequestLimitInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisTemplate<Object ,Object> redisTemplate;
    @Autowired
    private SystemFeignService systemFeignService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, java.lang.Object handler) throws Exception {
        HandlerMethod method = (HandlerMethod) handler;
        RequestIntercept methodAnnotation = method.getMethodAnnotation(RequestIntercept.class);
        RequestIntercept classAnnotation = method.getBean().getClass().getAnnotation(RequestIntercept.class);
        request.setCharacterEncoding("UTF-8");
        String[] split = request.getRequestURI().split("/");
        String phone = split[split.length - 1];
        if (methodAnnotation != null){
            log.info("方法注解限制频率");
            String ip = RequestUtil.getIP(request);
            String url = request.getRequestURL().toString();
            String key = "intercept_".concat(url).concat(ip);
            Long count = redisTemplate.opsForValue().increment(key, 1);
            int maxSize = methodAnnotation.count();
            long timeOut = methodAnnotation.time();
            if (count == 1 ){
                redisTemplate.expire(key, timeOut, TimeUnit.MILLISECONDS);
                return true;
            }
            if (count > maxSize ) {
                // OpenFeign拉黑
                systemFeignService.sava(Blacklist.builder()
                        .ip(ip).name(phone).phone(phone).createdTime(new Date()).status(1).build());
                log.info(" 当前访问次数: " + count + ",已经成功限制!");
                 return  false;
            }
        } else if (classAnnotation != null){
            log.info("类注解限制频率");
            return false;
        }else {
            return true;
        }
        return true;
    }

}

没来得急优化代码,将就看吧。大致的逻辑就是:将我们的自定义注解使用在Controller的相应方法上。当我们请求就会就进入拦截器,判断当前请求是否是小于规定次数,小于就放行,大于就拦截,并使用canal同步信息到Redis,进行拉黑用户禁止后续操作(建议拉黑IP地址)

2:配置拦截器

在MVC项目中需要这样配置

在SpringBoot项目中,交给容器使用。

@Configuration
public class ResourcesConfig implements WebMvcConfigurer{
    @Autowired
    private RequestLimitInterceptor repeatSubmitInterceptor;

    /**
     * 自定义拦截规则
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
    }

}

3:测试效果

第一次访问效果:

第二次访问效果:

数据库信息:

canal同步信息:

 RocketMQ的可视化工具,已经接受到消息对象。在项目中写一个消费监听器,自动同步Redis即可。当用户再次登录获取IP,或其他参数进行业务处理即可。

总结

以上就是今天要讲的内容,有任何问题欢迎留言

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,针对用户注册的黑盒测试接口,以下是一些测试用例设计: 1. 测试用例名称:输入正确的用户名和密码,注册成功 测试步骤: - 输入合法的用户名和密码 - 点击注册按钮 - 检查是否成功跳转到登录页面 - 使用新注册的用户名和密码登录,检查是否可以成功登录 2. 测试用例名称:输入已存在的用户名,注册失败 测试步骤: - 输入已存在的用户名和一个合法的密码 - 点击注册按钮 - 检查是否出现错误提示,提示用户名已存在 3. 测试用例名称:输入过短的密码,注册失败 测试步骤: - 输入一个合法的用户名和一个过短的密码 - 点击注册按钮 - 检查是否出现错误提示,提示密码过短 4. 测试用例名称:输入非法的用户名,注册失败 测试步骤: - 输入一个非法的用户名,如包含特殊字符或长度超过限制 - 输入一个合法的密码 - 点击注册按钮 - 检查是否出现错误提示,提示用户名非法 5. 测试用例名称:输入非法的密码,注册失败 测试步骤: - 输入一个合法的用户名 - 输入一个非法的密码,如包含特殊字符或长度超过限制 - 点击注册按钮 - 检查是否出现错误提示,提示密码非法 6. 测试用例名称:不输入用户名和密码,注册失败 测试步骤: - 不输入用户名和密码 - 点击注册按钮 - 检查是否出现错误提示,提示用户名和密码不能为空 7. 测试用例名称:输入不同的密码和确认密码,注册失败 测试步骤: - 输入一个合法的用户名 - 输入两个不同的密码,一个作为密码,一个作为确认密码 - 点击注册按钮 - 检查是否出现错误提示,提示两次输入的密码不一致 以上是一些基本的测试用例设计,可以通过修改一些参数和操作来衍生更多的测试用例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有头发的Java程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值