天天看點

Spring AOP實作接口安全認證利用Spring AOP解密請求參數,實作接口安全認證

利用Spring AOP解密請求參數,實作接口安全認證

在寫接口的時候經常會遇到需要進行安全認證的場景,如果是一兩個接口寫個公共的安全檢查方法,然後每個接口去調用一下就可以了,但是如果接口很多,這個過程就顯得有點繁瑣了,由于工作需要是以看了幾篇通過SpringAOP實作的,自己也在項目中實驗了一下,代碼如下。

Spring AOP有什麼環繞通知,前置後置通知,大家可以具體看下關于這幾個通知的含義及用法。
           

自定義一個注解,@Security.java,代碼如下

package com.light.api.helper.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.light.api.constant.Authority;

/**
 * 
 * @Description: 自定義安全驗證注解
 *
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Security {

    /**
     * 
     * @Title: sign
     * @Description: 簽名字段
     * @return String[]
     * @throws
     */
    String[] sign() default {};

    /**
     * 
     * @Title: field
     * @Description: 加密的字段
     * @return String[]
     * @throws
     */
    String[] field() default {};

    /**
     * 
     * @Title: method
     * @Description: 
     * @return Authority
     * @throws
     */
    Authority method() default Authority.DEFAULT_ACCESS;
}
           

Spring AOP的具體實作類

package com.light.api.helper.aop;

import java.util.Arrays;

import javax.annotation.Resource;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 
 * @Description: 接口安全驗證AOP
 *
 */
@Aspect
@Component
public class SecurityAOP {

    private static final Logger logger = LoggerFactory.getLogger(SecurityAOP.class);

    @Resource
    private TrafficPermissionManager<TrafficPermission> trafficPermissionManager;

    /**
     * 在所有标注@Security的地方切入
     */
    @Before("@annotation(com.light.api.helper.annotation.Security)")
    public void beforeExec(JoinPoint joinPoint) throws IOException {
    }

    @After("@annotation(com.light.api.helper.annotation.Security)")
    public void afterExec(JoinPoint joinPoint) {
    }

    @AfterThrowing(value = "@annotation(com.light.api.helper.annotation.Security)", throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint, Exception ex) {
        String methodName = joinPoint.getSignature().getName();
        logger.error("@AfterThrowing-->The method {} occurs exception:{}", methodName, ex);
    }

    @Around("@annotation(com.light.api.helper.annotation.Security)")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        logger.info("@Around start ...");
        MethodSignature ms = (MethodSignature) point.getSignature();
        Authority authority = ms.getMethod().getAnnotation(Security.class).method();
        String[] signs = ms.getMethod().getAnnotation(Security.class).sign();
        String[] fields = ms.getMethod().getAnnotation(Security.class).field();
        Object[] args = point.getArgs();
        for (int i = ; i < args.length; i++) {
            if (args[i] instanceof SecurityRequest) {
                // 需要實作的業務邏輯
                // 在這兒可以對參數進行解密操作,并指派給args[i]中,傳遞到目标方法中。然後在目标方法中就可以使用已經解密的參數了。
            }
            if (args[i] instanceof String) {
                // 需要實作的業務邏輯
            }
        }
        // 這個很重要
        Object response = point.proceed(args);
        // 在這塊可以記日志。
        return response;
    }
}
           

因為使用的是注解方式的AOP,是以隻需要在SpringMVC.xml配置檔案中添加下面這段代碼就可以了

controller中的代碼如下:

@Security(sign = { "aaa", "bbb" }, fields = { "aaa", "bbb" }, method = Authority.TEST)
    @RequestMapping(value = { "/test", "/test1" }, method = { RequestMethod.POST }, produces = {
            "application/json" }, consumes = { "application/json" })
    @ResponseBody
    public SecurityResponse test(@RequestBody TrafficRequest trafficRequest, String request) {
        //具體實作
        return null;
    }
           
到這裡基本就可以了,大家可以根據需要具體實作。
           

繼續閱讀