springboot2 指定ip_SpringBoot实现限制ip访问次数

该博客介绍如何在SpringBoot2应用中利用自定义注解和AOP实现IP访问次数限制。通过定义RequestLimit注解设置最大访问次数和时间间隔,并在请求到达时检查IP访问计数,超过限制则抛出异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://blog.csdn.net/qq_38095094/article/details/78709433 有时候存在着一些恶意访问的情况,为了阻止这种情况的发生,我们可以写一个拦截器,当某个IP的访问在单位时间内超过一定的次数时,将禁止他继续访问。 在这里我们使用了SpringBoot搭配注解来使用 除了springboot需要的依赖之外,我们还需要加上Aspect依赖

org.springframework

spring-aspects

4.3.10.RELEASE

我们可以自定义一个注解,里面填入单位时间长度和单位时间访问的最大次数

package com.example.web.demo.test;

import org.springframework.core.Ordered;

import org.springframework.core.annotation.Order;

import java.lang.annotation.*;

/**

@time:

@Discription: / @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented @Order(Ordered.HIGHEST_PRECEDENCE) public @interface RequestLimit { /*

允许访问的最大次数 */ int count() default Integer.MAX_VALUE;

/**

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

接下来我们要定义一个异常类

package com.example.web.demo.test;

/**

@Author:高键城

@time:

@Discription: */

public class RequestLimitException extends Exception {

private static final long serialVersionUID = 1364225358754654702L;

public RequestLimitException(){

super("HTTP请求超出设定的限制");

}

public RequestLimitException(String message){

super(message);

}

}

有了注解之后,我们要对注解实行一些相应的操作

package com.example.web.demo.test;

import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; import java.util.Timer; import java.util.TimerTask;

/**

@author Administrator

@time:

@Discription: */

@Aspect

@Component

public class RequestLimitContract {

private static final Logger logger = LoggerFactory.getLogger("requestLimitLogger");

private Map redisTemplate = new HashMap<>();

@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 = null;

for (int i = 0; i < args.length; i++) {

if (args[i] instanceof HttpServletRequest) {

request = (HttpServletRequest) args[i];

break;

}

}

if (request == null) {

throw new RequestLimitException("方法中缺失HttpServletRequest参数");

}

String ip = request.getLocalAddr();

String url = request.getRequestURL().toString();

String key = "req_limit_".concat(url).concat(ip);

if (redisTemplate.get(key) == null || redisTemplate.get(key) == 0) {

redisTemplate.put(key, 1);

} else {

redisTemplate.put(key, redisTemplate.get(key) + 1);

}

int count = redisTemplate.get(key);

if (count > 0) {

//创建一个定时器

Timer timer = new Timer();

TimerTask timerTask = new TimerTask() {

@Override

public void run() {

redisTemplate.remove(key);

}

};

//这个定时器设定在time规定的时间之后会执行上面的remove方法,也就是说在这个时间后它可以重新访问

timer.schedule(timerTask, limit.time());

}

if (count > limit.count()) {

logger.info("用户IP[" + ip + "]访问地址[" + url + "]超过了限定的次数[" + limit.count() + "]");

throw new RequestLimitException();

}

}catch (RequestLimitException e){

throw e;

}catch (Exception e){

logger.error("发生异常",e);

}

}

}

@before 注解代表在请求发送到控制器之前会先来到这里执行相应的内容,within里面的书写表示写在控制器上方并且有对应注解的控制器会来到这里。 在获得ip和对应的url之后将它作为一个key,存放到map中,假如map中已经存在了这个key,那么多产生一个时间处理器,当时间超过注解书写的单位时间之后又会将这个key从map中移走。 假如访问的次数超过了限制,将会抛出异常说明访问次数过多 最后在使用控制器的时候加上对应的注解即可

@Controller

public class testController{

@RequestMapping("/hello")

@RequestLimit(count=10,time=60000)

public String test(HttpServletRequest request){

return "hello";

}

}

小结:值得注意的是实现RequestLimit注解的方法必须有HttpServletRequest参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值