1.聲名註解
package com.eternalray.conf;
import java.lang.annotation.*;
/**
* 安全認證
* @author EternalRay
*/
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Authorized {
}
2.定義切面
package com.eternalray.conf;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
/**
* 安全切面認證配置
* @author EternalRay
*/
@Aspect
@Order(0)
@Component
@Slf4j
public class AuthorizedAspectConf {
/**
* 請求頭認證字段
*/
private static final String HEAD_AUTHORIZATION="Authorization";
/**
* 請求切點方法(已提供@RequestMapping,@GetMapping,@PostMapping註解,需要其它請增加)
*/
@Pointcut(" @annotation(org.springframework.web.bind.annotation.RequestMapping) || " +
" @annotation(org.springframework.web.bind.annotation.GetMapping) || " +
" @annotation(org.springframework.web.bind.annotation.PostMapping)")
void requestMapping() {
}
/**
* 範圍切點方法
*/
@Pointcut("execution(* com.eternalray.controller.*.*(..))")
public void methodPointCut() {
}
/**
* 某個方法執行前進行請求合法性認證 注入Authorized註解 (先)
*/
@Before("requestMapping() && methodPointCut() && @annotation(authorized)")
void doBefore(JoinPoint joinPoint, Authorized authorized) throws Exception{
Class type = joinPoint.getSignature().getDeclaringType();
Annotation[] annotations = type.getAnnotationsByType(Authorized.class);
if (ObjectUtils.isEmpty(annotations)) {
log.info("進入AOP方法認證...");
authLogic(joinPoint);
}
}
/**
* 類下面的所有方法執行前進行請求合法性認證 (後)
*/
@Before("requestMapping() && methodPointCut()")
void doBefore(JoinPoint joinPoint) throws Exception {
Class type = joinPoint.getSignature().getDeclaringType();
Annotation[] annotations = type.getAnnotationsByType(Authorized.class);
if (!ObjectUtils.isEmpty(annotations)) {
log.info("進入AOP類認證...");
authLogic(joinPoint);
}
}
/**
* 認證邏輯
* @param joinPoint
* @throws Exception
*/
private void authLogic(JoinPoint joinPoint) throws Exception {
log.info("認證開始...");
String classType = joinPoint.getTarget().getClass().getName();
Class<?> clazz = Class.forName(classType);
String clazzName = clazz.getName();
String methodName = joinPoint.getSignature().getName();
log.info("ClassName: "+clazzName);
log.info("MethodName:"+methodName);
//獲取當前http請求
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String token = request.getHeader(HEAD_AUTHORIZATION);
//此處的TOKEN驗證業務邏輯自行編寫
if(StringUtils.isNotEmpty(token)){
log.debug("請求認證通過!");
}else {
throw new Exception("請求被拒絕!");
}
}
}
3.控制層
package com.eternalray.controller;
import com.eternalray.conf.Authorized;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
* Authorized註解作用在類上時該類所有方法將進行AOP
* Authorized註解作用在方法時將對方法進行AOP
* 二者同時存在不會重複執行AOP,將會執行AOP類認證
*/
/**
* @author EternalRay
*/
@Authorized
@RestController
public class TestController {
@Authorized
@GetMapping("/get")
Object get(){
Map<String,String> map = new HashMap<>(1);
map.put("get","getValue");
return map;
}
@PostMapping("/get2")
Object get2(){
Map<String,String> map = new HashMap<>(1);
map.put("get2","get2Value");
return map;
}
}
4.完整POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.eternalray</groupId>
<artifactId>aop</artifactId>
<version>1.0</version>
<name>aop</name>
<description>AOP</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
5.全局異常捕獲
注:該文參考以下鏈接後進行內容原創
參考鏈接:https://www.cnblogs.com/jeffwongishandsome/archive/2018/06/08/9090374.html