天行健,君子以自强不息;地势坤,君子以厚德载物。
每个人都有惰性,但不断学习是好好生活的根本,共勉!
文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。
文章目录
- 一、前言
- 二、代码
- 1. 依赖pom.xml
- 2. 主程序类Application.java
- 3. 请求控制类AopController.java
- 4. Aop拦截类AspectExecution.java
- 三、执行
- 1. 执行程序
- 2. 发送请求
- 3. 控制台输出
一、前言
关于AOP的使用可参考: Java AOP 简单实例演示
本篇使用AOP的 @Before注解进行全局请求的拦截,并在所有拦截的请求执行前进行请求参数的校验,校验通过则执行请求,校验不通过则抛错终止所拦截的请求。
具体:
在用户登录时,后端生成一个token字符串,存入redis并定义过期时间,同时给到前端,此时前端的操作每个请求都会带着请求的缓存进行访问调用
服务中的每个请求头中都含有token的参数值,用户每次访问调用一个接口时都会被aop拦截进行token校验
redis中的token与用户请求时的token一致则正常执行,不一致则抛错终止该请求的执行
二、代码
1. 依赖pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.3</version>
</dependency>
<!--集成Redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.7.3</version>
</dependency>
<!--json 工具-->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.33</version>
</dependency>
<!--项目注解工具-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<!--aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.7.3</version>
</dependency>
</dependencies>
2. 主程序类Application.java
import org.aspectj.lang.annotation.Aspect;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @ClassDescription:
* @JdkVersion: 1.8
* @Author: 李白
* @Created: 2024/3/18 14:12
*/
@Aspect
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
3. 请求控制类AopController.java
import com.alibaba.fastjson2.JSONObject;
import org.springframework.web.bind.annotation.*;
/**
* @ClassDescription: aop 测试请求类
* @JdkVersion: 1.8
* @Author: 李白
* @Created: 2024/3/18 15:38
*/
@RestController
@RequestMapping("/aop")
public class AopController {
@PostMapping("/test")
public JSONObject test(@RequestHeader("token")String token,
@RequestHeader("userGroup")String userGroup,
@RequestHeader("username")String username){
System.out.println("登录请求触发==========================》》》》》》》》》》》》》》》》");
System.out.println("request token: "+token);
//定义json对象,存储用户登录信息
JSONObject loginInfo = new JSONObject();
loginInfo.put("userGroup", userGroup);
loginInfo.put("username", username);
loginInfo.put("token", token);
System.out.println("登录请求结束===================================》》》》》》》》》》》》》》》》》》》》》");
return loginInfo;
}
}
4. Aop拦截类AspectExecution.java
import com.u.u.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* @ClassDescription:
* @JdkVersion: 1.8
* @Author: 李白
* @Created: 2024/3/20 10:34
*/
@Aspect
@Component
@Slf4j
@Order(2)
public class TokenAspectExecution {
@Autowired
RedisUtil redisUtil;
//指定被切入点的方法列表,表示只对aop_test包中以Controller结尾的所有方法生效
@Pointcut("execution(public * com..aop_test.*Controller.*(..))")
//@Pointcut("execution(public * com..*Controller.*(..))")
public void sig(){}
@Before("sig()")
public void beforeRequest(){
log.info("-----------前置通知-----------");
ServletRequestAttributes srAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
assert srAttributes != null;
HttpServletRequest hsRequest = srAttributes.getRequest();
String token = hsRequest.getHeader("token");
String username = hsRequest.getHeader("username");
System.out.println("token:" + token);
System.out.println("username: " + username);
//获取到token后去redis中查看
//redis中是否含有token的key
boolean hasToken = redisUtil.hasKey("login#" + username);
// boolean hasToken = true;
Object object = redisUtil.get("login#" + username);
//redis中的token是否与传入的token一致
boolean isToken = object.toString().equals(token);
// boolean isToken = false;
if (hasToken){
//token存在,进行验证,
System.out.println("token存在,进行验证");
if (isToken){
//token校验通过,放行
System.out.println("token一致,校验通过,请求放行");
}else {
//token验证未通过,返回请求失败
System.out.println("token不一致,校验失败,请求拒绝");
throw new RuntimeException("token不一致,校验失败,请求拒绝");
}
}else {
//验证不通过,请求退回
//redis中没有token的键,说明没有登录或登录时间过期(4小时)
System.out.println("token不存在,未登录或token过期");
throw new RuntimeException("token不存在,未登录或token过期");
}
}
}
三、执行
1. 执行程序
启动主程序运行服务
2. 发送请求
postman发送请求
3. 控制台输出
token不一致,请求中断
感谢阅读,祝君暴富!