天天看点

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;
    }
           
到这里基本就可以了,大家可以根据需要具体实现。
           

继续阅读