工作杂记-AOP

该文章介绍了如何在JavaSpring环境中创建一个自定义注解`UserPermission`,用于在控制器层进行权限验证。注解可以包含EL表达式,以便从请求参数中动态获取权限信息。AOP切面`UserPermissionAop`处理注解,检查用户token并验证角色权限,如果权限不足则抛出业务异常。
摘要由CSDN通过智能技术生成
自定义切面使用:
注解类:
package com.xx.datamanage.controller.aop;

import org.springframework.core.annotation.AliasFor;

import java.lang.annotation.*;

/**
 * @author dasong
 * @version 1.0
 * @desc TODO
 * @class UserPermission
 * @date 2022/11/16 17:25
 */
@Target({ElementType.METHOD}) //用于标明注解的作用范围
@Retention(RetentionPolicy.RUNTIME) //用于标明注解的生命周期
@Documented  //用于标明该注解将会被包含在javadoc中
public @interface UserPermission {

    @AliasFor("rbacToken")
    String value() default "";
}

aop切面类
package com.xx.datamanage.controller.aop;

import com.xx.common.bean.base.LoginInfo;
import com.xx.common.service.FyRedisManage;
import com.xx.datamanage.exception.BusinessException;
import com.xx.datamanage.mapper.AuthorMapper;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.expression.AnnotatedElementKey;
import org.springframework.expression.EvaluationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author dasong
 * @version 1.0
 * @desc TODO
 * @class UserPermissionAop
 * @date 2022/11/16 17:13
 */
// 注解将一个java类定义为切面类
@Aspect
@Component
public class UserPermissionAop {

    private static Logger log = LoggerFactory.getLogger(UserPermissionAop.class);
    // EL 表达式解析器
    private static final ExpressionEvaluator<String> EVALUATOR = new ExpressionEvaluator<>();
    @Resource
    private AuthorMapper authorMapper;
    @Resource
    private FyRedisManage fyRedisManage;

    @Pointcut(value = "@annotation(permission)", argNames = "permission")
    public void pointcut(com.fy.datamanage.controller.aop.UserPermission permission) {
    }

    @Around(value = "pointcut(permission)", argNames = "joinPoint,permission")
    public Object around(ProceedingJoinPoint joinPoint, UserPermission permission) throws Throwable {
        String rbacToken = "";
        String permissionValue = permission.value();
        if (StringUtils.isNotBlank(permissionValue)) {
            // 解析EL表达式
            rbacToken = this.evalLockParam(joinPoint, permissionValue);
        }
        if (StringUtils.isBlank(rbacToken)) {
            //获取上下文request,获取token并解析
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
            rbacToken = request.getParameter("rbacToken");
        }
        if (StringUtils.isBlank(rbacToken)) {
            throw new BusinessException("请传入用户token", 1001);
        }
        LoginInfo loginInfo = fyRedisManage.getLoginInfo(rbacToken);
        if (Objects.isNull(loginInfo) || StringUtils.isBlank(loginInfo.getUserId())) {
            throw new BusinessException("当前用户不存在", 1002);
        }
        String roleId = authorMapper.getRoleIdByUserId(loginInfo.getUserId());
        if (StringUtils.isBlank(roleId) || roleId.equals("role2")) {
            log.info("当前用户无此权限");
            throw new BusinessException("当前用户无权限", 1003);
        }
        return joinPoint.proceed();
    }

    /**
     * 解析EL表达式
     * @param point 切入点
     * @param lockParam 需要解析的EL表达式
     * @return 解析出的值
     */
    private String evalLockParam(ProceedingJoinPoint point, String lockParam) {
        MethodSignature ms = (MethodSignature) point.getSignature();
        Method method = ms.getMethod();
        Object[] args = point.getArgs();
        Object target = point.getTarget();
        Class<?> targetClass = target.getClass();
        EvaluationContext context = EVALUATOR.createEvaluationContext(target, target.getClass(), method, args);
        AnnotatedElementKey elementKey = new AnnotatedElementKey(method, targetClass);
        return EVALUATOR.condition(lockParam, elementKey, context, String.class);
    }
}

使用注解
	// 方式一
	@UserPermission
    @GetMapping("/page")
    public BaseResponse page(PageRequest page){
        return ResponseUtil.success(this.service.getPage(page));
    }

	// 方式二
	@UserPermission("#dto.rbacToken")
    @RequestMapping(value = "/addUser", method = RequestMethod.POST)
    public BaseResponseVO addUser(@RequestBody UserAddDTO dto) {
    	this.service.addUser(dto);
        return ResponseVOUtil.success("新增成功");
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值