springboot接口服務(wù),防刷、防止請求攻擊,AOP實現(xiàn)方式
更新時間:2024年11月22日 14:45:53 作者:十&年
本文介紹了如何使用AOP防止Spring?Boot接口服務(wù)被網(wǎng)絡(luò)攻擊,通過在pom.xml中加入AOP依賴,創(chuàng)建自定義注解類和AOP切面,以及在業(yè)務(wù)類中使用這些注解,可以有效地對接口進(jìn)行保護(hù),測試表明,這種方法有效地防止了網(wǎng)絡(luò)攻擊
springboot接口服務(wù),防刷、防止請求攻擊,AOP實現(xiàn)
本文使用AOP的方式防止spring boot的接口服務(wù)被網(wǎng)絡(luò)攻擊
pom.xml 中加入 AOP 依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>AOP自定義注解類
package org.jeecg.common.aspect.annotation;
import java.lang.annotation.*;
/**
* 用于防刷限流的注解
* 默認(rèn)是5秒內(nèi)只能調(diào)用一次
*/
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimit {
/** 限流的key */
String key() default "limit:";
/** 周期,單位是秒 */
int cycle() default 5;
/** 請求次數(shù) */
int count() default 1;
/** 默認(rèn)提示信息 */
String msg() default "請勿重復(fù)點擊";
}AOP切面業(yè)務(wù)類
package org.jeecg.common.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.jeecg.common.aspect.annotation.RateLimit;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
/**
* 切面類:實現(xiàn)限流校驗
*/
@Aspect
@Component
public class AccessLimitAspect {
@Resource
private RedisTemplate<String, Integer> redisTemplate;
/**
* 這里我們使用注解的形式
* 當(dāng)然,我們也可以通過切點表達(dá)式直接指定需要攔截的package,需要攔截的class 以及 method
*/
@Pointcut("@annotation(org.jeecg.common.aspect.annotation.RateLimit)")
public void limitPointCut() {
}
/**
* 環(huán)繞通知
*/
@Around("limitPointCut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
// 獲取被注解的方法
MethodInvocationProceedingJoinPoint mjp = (MethodInvocationProceedingJoinPoint) pjp;
MethodSignature signature = (MethodSignature) mjp.getSignature();
Method method = signature.getMethod();
// 獲取方法上的注解
RateLimit rateLimit = method.getAnnotation(RateLimit.class);
if (rateLimit == null) {
// 如果沒有注解,則繼續(xù)調(diào)用,不做任何處理
return pjp.proceed();
}
/**
* 代碼走到這里,說明有 RateLimit 注解,那么就需要做限流校驗了
* 1、這里可以使用Redis的API做計數(shù)校驗
* 2、這里也可以使用Lua腳本做計數(shù)校驗,都可以
*/
//獲取request對象
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 獲取請求IP地址
String ip = getIpAddr(request);
// 請求url路徑
String uri = request.getRequestURI();
//存到redis中的key
String key = "RateLimit:" + ip + ":" + uri;
// 緩存中存在key,在限定訪問周期內(nèi)已經(jīng)調(diào)用過當(dāng)前接口
if (redisTemplate.hasKey(key)) {
// 訪問次數(shù)自增1
redisTemplate.opsForValue().increment(key, 1);
// 超出訪問次數(shù)限制
if (redisTemplate.opsForValue().get(key) > rateLimit.count()) {
throw new RuntimeException(rateLimit.msg());
}
// 未超出訪問次數(shù)限制,不進(jìn)行任何操作,返回true
} else {
// 第一次設(shè)置數(shù)據(jù),過期時間為注解確定的訪問周期
redisTemplate.opsForValue().set(key, 1, rateLimit.cycle(), TimeUnit.SECONDS);
}
return pjp.proceed();
}
//獲取請求的歸屬IP地址
private String getIpAddr(HttpServletRequest request) {
String ipAddress = null;
try {
ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
}
// 對于通過多個代理的情況,第一個IP為客戶端真實IP,多個IP按照','分割
if (ipAddress != null && ipAddress.length() > 15) {
// = 15
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
} catch (Exception e) {
ipAddress = "";
}
return ipAddress;
}
}測試
package org.jeecg.modules.api.controller;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.RateLimit;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 測試接口
* @author wujiangbo
* @date 2022-08-23 18:50
*/
@RestController
@RequestMapping("/test")
public class TestController {
//4秒內(nèi)只能訪問2次
@RateLimit(key= "testLimit", count = 2, cycle = 4, msg = "大哥、慢點刷請求!")
@GetMapping("/test001")
public Result<?> rate() {
System.out.println("請求成功");
return Result.OK("請求成功!");
}
}總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
您可能感興趣的文章:
- SpringBoot 攔截器 (Interceptor)與切面 (AOP)示例、作用及適用場景分析
- AOP在SpringBoot項目中的使用場景解讀
- SpringBoot整合Jasypt使用自定義注解+AOP實現(xiàn)敏感字段加解密
- Springboot如何正確使用AOP問題
- SpringBoot3利用AOP實現(xiàn)IP黑名單功能
- springbootAOP定義切點獲取/修改請求參數(shù)方式
- SpringBoot實現(xiàn)AOP切面的三種方式
- SpringBoot中使用AOP實現(xiàn)日志記錄功能
- SpringBoot AOP如何配置全局事務(wù)
- JAVA中Spring Boot的AOP切面編程是什么,如何使用?(實例代碼)
相關(guān)文章
java實現(xiàn)將結(jié)果集封裝到List中的方法
這篇文章主要介紹了java實現(xiàn)將結(jié)果集封裝到List中的方法,涉及java數(shù)據(jù)庫查詢及結(jié)果集轉(zhuǎn)換的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2016-07-07
SpringSecurity+jwt+captcha登錄認(rèn)證授權(quán)流程總結(jié)
本文介紹了SpringSecurity、JWT和驗證碼在Spring Boot 3.2.0中的應(yīng)用,包括登錄認(rèn)證和授權(quán)流程的詳細(xì)步驟,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-11-11
Javaee多線程之進(jìn)程和線程之間的區(qū)別和聯(lián)系(最新整理)
進(jìn)程是資源分配單位,線程是調(diào)度執(zhí)行單位,共享資源更高效,創(chuàng)建線程五種方式:繼承Thread、Runnable接口、匿名類、lambda,run為方法,start啟動線程,實現(xiàn)并發(fā)執(zhí)行,本文給大家介紹Javaee多線程之進(jìn)程和線程之間的區(qū)別和聯(lián)系,感興趣的朋友跟隨小編一起看看吧2025-07-07
基礎(chǔ)不牢,地動山搖,Java基礎(chǔ)速來刷刷
基礎(chǔ)不牢,地動山搖,快來一起學(xué)習(xí)一下基礎(chǔ)吧,不斷地學(xué)習(xí)就算是基礎(chǔ)也會有新的認(rèn)知和收獲,加油2021-08-08
基于Java SWFTools實現(xiàn)把pdf轉(zhuǎn)成swf
這篇文章主要介紹了基于Java SWFTools實現(xiàn)把pdf轉(zhuǎn)成swf,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-11-11

