SpringAop实现权限校验与日志打印

使用springboot+aop实现用户的权限校验与日志的打印

Base切面

/**
 * @Description 基础切面类
 * @author xpWang
 * @date 2020/1/6 16:13
 */
public class BaseAspect {
     
    protected Method method;
    protected Class clazz;
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping) || "
            + "@annotation(org.springframework.web.bind.annotation.GetMapping) || "
            + "@annotation(org.springframework.web.bind.annotation.PostMapping)||"
            + "@annotation(org.springframework.stereotype.Controller)||"
            + "@annotation(org.springframework.web.bind.annotation.RestController)")
    void requestMapping() {
     
    }
    protected void init(JoinPoint joinPoint) throws NoSuchMethodException {
     
        clazz = joinPoint.getTarget().getClass();
        Signature signature = joinPoint.getSignature();
        MethodSignature msg = (MethodSignature) signature;
        method = clazz.getMethod(msg.getName(), msg.getParameterTypes());
    }
}

权限校验父类

/**
 * @Description 用户信息相关切面
 * @author xpWang
 * @date 2020/1/6 16:13
 */
@Slf4j
public class BaseTokenAspect extends BaseAspect{
     

    @Autowired
    private IAuthinfoService authinfoService;
    protected String token;
    protected AuthInfo authInfo;

    @Override
    protected void init(JoinPoint joinPoint) throws NoSuchMethodException {
     
        super.init(joinPoint);
        token = RequestUtil.getToken();
        if (StringUtils.isNotEmpty(token)) {
     
            try {
     
                authInfo = authinfoService.getAuthInfo(token);
            } catch (Exception e) {
     
                log.warn("authinfoService getAuthInfo exceprtion :"+e);
            }
        }
    }

    protected ErrorCode checkToken()  {
     
        log.info("check auth.");
        if (StringUtils.isEmpty(token)) {
     
            return ErrorCode.TOKEN_NOTOKEN;
        }
        return authinfoService.checkToken(token);
    }

    protected Object[] getAuthinfoArgs(JoinPoint joinPoint) throws Exception {
     
        Object[] args = joinPoint.getArgs();
        int index=checkParameterHasAuth(method);
        if (index!=-1){
     
            log.info("set authinfo");
            if (authInfo!=null){
     
                args[index]=authInfo;
            }else{
     
                log.warn("there is no cache");
            }
        }
        return args;
    }

    /**
     * @Description 检查方法参数是否有cn.com.taiji.system.domain.rbac.AuthInfo
     * @return int 返回参数AuthInfo所在Index,如果没有返回-1
     * @author xpWang
     * @date 2020/1/6 11:43
     */
    private int checkParameterHasAuth(Method method){
     
        Class<?>[] parameterTypes = method.getParameterTypes();
        for(int i=0;i<parameterTypes.length;i++){
     
            if (parameterTypes[i].isAssignableFrom(AuthInfo.class)){
     
                return i;
            }
        }
        return -1;
    }


}

token验证切面


/**
 * @Description 验证token注入auth
 * @author xpWang
 * @date 2020/1/6 16:14
 */
@Aspect
@Component
@Slf4j
@Order(1)
public class TokenMethodAspect extends BaseTokenAspect{
     

 @Around("requestMapping()&&@annotation(cn.com.taiji.framework.annotation.TokenMethod)")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
     
        try {
     
            this.init(joinPoint);
            Annotation[] annotations = method.getAnnotationsByType(TokenMethod.class);
            if (ObjectUtils.isEmpty(annotations)) {
     
                return joinPoint.proceed();
            }
            log.info("ClassName:\t" + clazz.getSimpleName()+"\tMethodName:\t" + method.getName());
            ErrorCode errorCode=checkToken();
            if (ErrorCode.TOKEN_CHECK_SUCCESS!=errorCode){
     
                log.error(errorCode.toJsonString());
                return new ObjectResponse(errorCode);
            }
            Object[] args=this.getAuthinfoArgs(joinPoint);
            return joinPoint.proceed(args);
        } catch (NoSuchMethodException e) {
     
            return new ObjectResponse().error("token aspect init exception.");
        } catch (Exception ex){
     
            return new ObjectResponse().error("token aspect doarround exception",ex);
        }
    }
}

权限校验切面


/**
 * @Description 验证token,permission注入auth
 * @author xpWang
 * @date 2020/1/6 16:14
 */

@Aspect
@Component
@Slf4j
@Order(2)
public class TokenPermissionMethodAspect extends BaseTokenAspect {
     
    /**
     * @Description 验证token, 注入Auth
     * @author xpWang
     * @date 2020/1/6 14:53
     */
    @Around("requestMapping()&&@annotation(cn.com.taiji.framework.annotation.TokenPermissionMethod)")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
     
        if (!RequestUtil.isNeedPermission()){
     
            log.debug("checkAuthPermission isNeedPermission is false.");
            return joinPoint.proceed();
        }
        try {
     
            this.init(joinPoint);
            log.info("ClassName:\t" + clazz.getSimpleName() + "\tMethodName:\t" + method.getName());
            ErrorCode errorCode = checkToken();
            if (ErrorCode.TOKEN_CHECK_SUCCESS != errorCode) {
     
                log.error(errorCode.toJsonString());
                return new ObjectResponse(errorCode);
            }
            ErrorCode perErrorCode = checkAuthPermission();
            if (ErrorCode.SUCCESS!=perErrorCode){
     
                log.error(perErrorCode.toJsonString());
                return new ObjectResponse(perErrorCode);
            }
            log.info("permission verify success.");
            TokenPermissionMethod annotation = method.getAnnotation(TokenPermissionMethod.class);
            if (annotation.onlyCheck()){
     
                return new ObjectResponse(ErrorCode.PERMISSION_CHECK_SUCCESS);
            }
            Object[] args = this.getAuthinfoArgs(joinPoint);
            return joinPoint.proceed(args);
        } catch (NoSuchMethodException e) {
     
            return new ObjectResponse().error("token aspect init exception.");
        } catch (Exception ex) {
     
            return new ObjectResponse().error("TokenPermissionMethodAspect aspect doAround exception", ex);
        }
    }

    /**
     * @Description 检查用户权限
     * @author xpWang
     * @date 2020/1/6 15:49
     */
    private ErrorCode checkAuthPermission(){
     
        if (authInfo == null) {
     
            return ErrorCode.PERMISSION_NO_CACHE;
        }
        Integer perId = RequestUtil.getPerId();
        Integer nodeId = RequestUtil.getNodeId();
        log.debug("checkAuthPermission perId:\t"+perId+"\tnodeId:\t"+nodeId);
        //check permission
        if (perId != null &&
                (authInfo.getPermissions() == null || !ArrayUtils.contains(authInfo.getPermissions(), perId))) {
     
            return ErrorCode.PERMISSION_FAILED;
        }

        if (nodeId != null &&
                (authInfo.getNodes() == null || !ArrayUtils.contains(authInfo.getNodes(), nodeId))) {
     
            return ErrorCode.PERMISSION_FAILED;
        }
        return ErrorCode.SUCCESS;

    }

}

controller日志记录
这里的方法参数打印有问题,需要修改

@Aspect
@Component
@Slf4j
@Order(1)
public class ControllerLogAspect extends BaseAspect{
     

    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping) || "
            + "@annotation(org.springframework.web.bind.annotation.GetMapping) || "
            + "@annotation(org.springframework.web.bind.annotation.PostMapping)")
    void requestLog() {
     
    }

    @Around("requestLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
     
        long begin=System.currentTimeMillis();
        init(joinPoint);
        log.debug("BEGIN:\tClassName:\t" + clazz.getSimpleName()+"\tMethodName:\t" + method.getName()+"\targs:\t"+JSON.toJSONString(joinPoint.getArgs(), SerializerFeature.WriteMapNullValue));
        //log.debug("BEGIN:\tClassName:\t" + clazz.getSimpleName()+"\tMethodName:\t" + method.getName()+"\targs:\t");
        Object result=joinPoint.proceed();
        log.debug("END:\tClassName:\t" + clazz.getSimpleName()+"\tMethodName:\t" + method.getName()+"\tCost:"+(System.currentTimeMillis()-begin)+"ms\tResult"+JSON.toJSONString(result));
        return result;
    }
}

annotation

/**
 * @Description  需要进行Token以及权限验证的Controller注解
 * @author xpWang
 * @date 2020/1/6 11:27
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TokenPermissionMethod {
     
    boolean onlyCheck() default false;
}

/**
 * @Description  需要进行Token验证的Controller注解
 * @author xpWang
 * @date 2020/1/6 11:27
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TokenMethod {
     

}

controller使用


/**
 * @Description 用户登录信息相关服务
 * @author xpWang
 * @date 2019/12/31 10:23
 */
@RestController
@RequestMapping("/authinfo")
@Api(tags = "账户权限管理系统-用户认证", value = "authinfo")
public class AuthInfoController extends BaseController {
     

    @Autowired
    private IAuthinfoService authinfoService;


    @PostMapping("/login")
    @ApiOperation(notes = "登录接口", value = "login")
    public AjaxResponse login(@RequestBody UserDO user) {
     
        ObjectResponse response=new ObjectResponse();
        AuthInfo auth = null;
        try {
     
            auth = authinfoService.login(user);
            if (auth == null) {
     
                return response.error("Incorrect user name or password");
            }
            return response.success("login success", auth);
        } catch (Exception e) {
     
            return response.error("login exception : " , e);
        }
    }


    /**
     * @Description AOP判断了
     * @author xpWang
     * @date 2020/1/6 16:14
     */
    @PostMapping("/checkAuth")
    @ApiOperation(notes = "登录信息权限校验", value = "checkAuth")
    @TokenPermissionMethod(onlyCheck = true)
    public AjaxResponse checkAuth() {
     
        return new ObjectResponse(ErrorCode.PERMISSION_CHECK_SUCCESS);
    }

    /**
     * 根据TOKEN获取账号信息
     */
    @PostMapping("/getAuthInfo")
    @ApiOperation(notes = "账号分页查询", value = "getAuthInfo")
    @TokenMethod
    public AjaxResponse getAuthInfo(AuthInfo authInfo) {
     
        ObjectResponse response=new ObjectResponse();
        try {
     
            if (authInfo != null) {
     
                return response.success("success.", authInfo);
            } else {
     
                return response.error("there is no authinfo in cache.");
            }
        } catch (Exception e) {
     
            e.printStackTrace();
            return response.error("getAuthInfo exception:\t",e);
        }
    }

    public AuthInfoController(){
     
        System.out.println("init AuthInfoController.");
    }

}

你可能感兴趣的:(Spring)