SpringBoot認證token的AOP實例

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章