應用場景二:使用注解+AOP對權限的校驗
在實際開發中,我們常常需要對方法進行權限控制,就比如對用戶身份的校驗,判斷其是不是管理員身份,此時我們就可以使用自定義注解+AOP進行權限的校驗
接下來我們開始演示一個Demo,管理員能夠訪問用戶和管理員對應的接口,而用戶只能訪問用戶的接口,並且還對登錄的用戶的用戶名和密碼進行校驗
使用到的依賴
<properties>
<java.version>1.8</java.version>
<spring-aop.version>5.2.8.RELEASE</spring-aop.version>
<aspectjweaver.version>1.8.7</aspectjweaver.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring-aop.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
</dependencies>
自定義@AdminLoginToken注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AdminLoginToken {
@AliasFor("admin")
boolean value() default true;
@AliasFor("value")
boolean admin() default true;
}
編寫兩個接口
@RestController
public class UserController {
/**
* 該接口用戶和管理員都可以進行訪問
* @return
*/
@GetMapping("/user")
@AdminLoginToken(false)
public TransDTO userLogin(){
return new TransDTO<>().withMessage("用戶頁面訪問成功!").withSuccess(true).withCode(200);
}
/**
* 該接口只有管理員可以進行訪問
* @return
*/
@AdminLoginToken()
@GetMapping("/admin")
public TransDTO adminLogin(){
return new TransDTO().withCode(200).withSuccess(true).withMessage("管理員頁面訪問成功!");
}
}
對AOP進行配置
@Component
@Aspect
public class AdminLoginTokenAOP {
/**
* 配置切入點表達式
*/
@Pointcut("@annotation(com.lq.annotationspringboot.annotation.AdminLoginToken)")
public void loginPointCut(){
}
/**
* 配置環繞通知
* @param point
* @return
*/
@Around("loginPointCut()")
public Object tokenHandler(ProceedingJoinPoint point) throws Throwable {
//1、獲取請求對象
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
//2、獲取請求頭
String loginToken = request.getHeader("login_token");
//3、獲取注解權限屬性
Class<?> aClass = point.getTarget().getClass();
//獲取方法簽名(通過此簽名獲得目標方法信息)
MethodSignature ms = (MethodSignature)point.getSignature();
Method method = aClass.getDeclaredMethod(ms.getName(),ms.getParameterTypes());
//獲取注解
AdminLoginToken annotation = method.getAnnotation(AdminLoginToken.class);
//獲取注解屬性
boolean admin = annotation.value();
//返回結果
Object o = null;
//這里可以根據和前端約定的格式對請求頭進行解析后查詢數據庫進行解析,也可以使用JWT自校驗框架進行token校驗,我們為了演示方便直接使用user和admin
if(!loginToken.equals("admin") && !loginToken.equals("user")){
throw new BusinessException("訪問失敗,用戶校驗失敗!");
}
if(admin){
if(!loginToken.equals("admin")){
throw new BusinessException("訪問失敗,只有管理員才能進行訪問");
}
//繼續執行方法
o = point.proceed(point.getArgs());
}else {
//繼續執行方法
o = point.proceed(point.getArgs());
}
return o;
}
}
業務異常類
public class BusinessException extends RuntimeException{
private String message;
private Integer code;
public BusinessException(String message){
super(message);
message = "業務異常"+message;
this.code = -4000;
this.message = message;
}
}
全局異常處理
@RestControllerAdvice
public class ExceptionAdvice {
@ExceptionHandler(Exception.class)
public TransDTO handleException(HttpServletRequest request,Exception e){
e.printStackTrace();
return new TransDTO().withCode(500).withMessage(e.getMessage()).withSuccess(false);
}
}
與前端交互標准對象
package com.lq.annotationspringboot.dto;
public class TransDTO<T> {
private String message;
private Integer code;
private T date;
private Boolean success;
public TransDTO withMessage(String message){
this.message = message;
return this;
}
public TransDTO withCode(Integer code){
this.code = code;
return this;
}
public TransDTO withDate(T date){
this.date = date;
return this;
}
public TransDTO withSuccess(Boolean success){
this.success = success;
return this;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public T getDate() {
return date;
}
public void setDate(T date) {
this.date = date;
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
}
用戶訪問用戶頁面結果
管理員訪問用戶頁面
用戶訪問管理員頁面
管理員訪問管理員頁面
這樣我們就實現了使用自定義注解+AOP實現權限的校驗了,只需要在需要進行校驗的接口上添加注解即可!