spring boot结合ehcache防止恶意刷新请求

说明

我们在把开发好的网站上线之前一定要考虑到别人恶意刷新你的网页这种情况,最大限度的去限制他们。否则往往这将搞垮你的应用服务器,想象一下某个恶意用户利用众多肉鸡在1分钟内请求你网页几十万次是个什么情形?
部分内容参考网络。

要达到什么效果?

我限制请求的用户,根据来访IP去记录它N分钟之内请求单一网页的次数,如果超过N次我就把这个IP添加到缓存黑名单并限制它3小时之内无法访问类型网页。

效果图

1分钟内请求单网页超过15次就被加入黑名单,冻结3小时!

在这里插入图片描述

开发步骤

采用AOP+Ehcache方式。(Redis也可以)
AOP用于拦截和逻辑判断,Ehcache负责计数和缓存。

配置ehcache

略。如有需要联系我。

创建注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@Order(Ordered.HIGHEST_PRECEDENCE)
public @interface RequestLimit {
    /**
     * 允许访问的最大次数
     */
    int count() default 15;

    /**
     * 时间段,单位为毫秒,默认值一分钟
     */
    long time() default 1000*60;
}

创建AOP

@Aspect
@Component
public class RequestLimitAspect {
    private static final Logger logger = LoggerFactory.getLogger(RequestLimit.class);

    @Autowired
    EhcacheUtil ehcacheUtil;

    @Before("within(@org.springframework.stereotype.Controller *) && @annotation(limit)")
    public void requestLimit(final JoinPoint joinPoint , RequestLimit limit) throws RequestLimitException {
        try {
            Object[] args = joinPoint.getArgs();
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String ip = IpUtil.getRemoteIp(request);
            String uri = request.getRequestURI().toString();
            String key = "req_"+uri+"_"+ip;
            String blackKey = "black_"+ip;  // 黑名单IP封锁一段时间
            int count = 0; // 访问次数
            // 判断是否在黑名单
            if (ehcacheUtil.contains("countcache",blackKey)){
                throw new RequestLimitException();
            }else{
                // 判断是否已存在访问计数
                if (!ehcacheUtil.contains("limitCache",key)) {
                    ehcacheUtil.put("limitCache",key,1);

                } else {
                    count = ehcacheUtil.getInt("limitCache",key)+1;
                    ehcacheUtil.put("limitCache",key,count);
                    if (count > limit.count()) {
                        logger.info("用户IP[" + ip + "]访问地址[" + uri + "]超过了限定的次数[" + limit.count() + "]");
                        // 加入黑名单
                        ehcacheUtil.put("countcache",blackKey,"badguy");
                        throw new RequestLimitException();
                    }
                }
            }


        }catch (RequestLimitException e){
            throw e;
        }catch (Exception e){
            logger.error("发生异常",e);
        }
    }
}

应用aop

找到要应用的接口加上注解@RequestLimit即可。

    @RequestLimit(count=10)
    @OperLog(operModule = "更多文章",operType = "查询",operDesc = "查询更多文章")
    @GetMapping("/more/{categoryId}")
    public String getMore(@PathVariable("categoryId") String categoryId, Model model, HttpServletRequest request) {
        // 略
    }

关于代码

有不明白的朋友可以联系我交流。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值