拦截RequiresPermissions权限标识获取逻辑,实现Controller多级权限拼接

业务场景:
Shiro权限校验
RequiresPermissions标签是优先获取方法上的注解信息,再从类上注解获取权限标识符
但是系统的 XxxController 层是继承的 ParentController,增删改查方法,在ParentController中,无法对增删改查的 RequiresPermissions 权限标签进行自定义
后台技术组合:Spring Boot、Spring Aop、Apache Shiro

逻辑分析:
1、aop 切面拦截 controller 对应调用的方法
2、获取对应方法的注解信息
3、使用对应的解析器解析获取到的注解信息
①、获取方法注解信息
②、获取类注解信息
③、返回注解信息
4、从注解获取权限标识符

 一:问题现状

AfterSaleController层的权限标识符为"pc:afterSale:",ParentController层添加方法的权限标识符为"add"。想要的效果"pc:afterSale:"+"add"的组合,即"pc:afterSale:add"

二:找到aop切入入口


import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

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.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import com.sunward.common.security.annotation.RequiresLogin;
import com.sunward.common.security.annotation.RequiresPermissions;
import com.sunward.common.security.auth.AuthUtil;

/**
 * 基于 Spring Aop 的注解鉴权
 * 
 * @author kong
 */
@Aspect
@Component
public class PreAuthorizeAspect
{
    /**
     * 构建
     */
    public PreAuthorizeAspect()
    {
    }

    /**
     * 定义AOP签名 (切入所有使用鉴权注解的方法)
     */
    public static final String POINTCUT_SIGN = " @annotation(com.common.security.annotation.RequiresLogin) || "
            + "@annotation(com.common.security.annotation.RequiresPermissions)";

    /**
     * 声明AOP签名
     */
    @Pointcut(POINTCUT_SIGN)
    public void pointcut()
    {
    }

    /**
     * 环绕切入
     * 
     * @param joinPoint 切面对象
     * @return 底层方法执行后的返回值
     * @throws Throwable 底层方法抛出的异常
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable
    {
        // 注解鉴权
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        checkMethodAnnotation(joinPoint.getThis().getClass(),signature.getMethod());
        try
        {
            // 执行原有逻辑
            Object obj = joinPoint.proceed();
            return obj;
        }
        catch (Throwable e)
        {
            throw e;
        }
    }
}

 三:编辑以下代码

/**
     * 对一个Method对象进行注解检查
     */
    public void checkMethodAnnotation(Class s,Method method) throws NoSuchFieldException, IllegalAccessException {
        // 校验 @RequiresLogin 注解
        RequiresLogin requiresLogin = method.getAnnotation(RequiresLogin.class);
        if (requiresLogin != null)
        {
            AuthUtil.checkLogin();
        }
        //父类控制层的注解信息
        RequiresPermissions ParentMethodAnnotation = AnnotationUtils.findAnnotation(s, RequiresPermissions.class);
        String[] ParentMethodValues = (ParentMethodAnnotation != null ? ParentMethodAnnotation.value() : null);
        // 校验 @RequiresPermissions 注解
        RequiresPermissions childMethodAnnotation = method.getAnnotation(RequiresPermissions.class);
        //子类控制层的注解信息
        String[] childMethodValues = (childMethodAnnotation != null ? childMethodAnnotation.value() : null);
        String[] newValue = new String[childMethodValues.length];
        //反序列化
        InvocationHandler invocationHandler = Proxy.getInvocationHandler(childMethodAnnotation);
        Field value = invocationHandler.getClass().getDeclaredField("memberValues");
        value.setAccessible(true);
        Map<String, Object> memberValues = (Map<String, Object>) value.get(invocationHandler);
        //遍历父类控制层的权限标识符
        if(ParentMethodValues!=null){
            if(ParentMethodAnnotation!=null){
                for (int i = 0; i<childMethodValues.length;++i
                ) {
                    //父类控制层的权限标识符跟子类控制层标识符组合
                    newValue[i] = ParentMethodValues[0]+childMethodValues[i];
                    memberValues.put("value", newValue);
                }
            }
            if (childMethodAnnotation != null)
            {
                AuthUtil.checkPermi(childMethodAnnotation);
            }
        }
        //还原
        memberValues.put("value", childMethodValues);
    }

觉得写的不错的朋友,请点点赞!❤❤❤❤❤❤❤❤

参考:

1、SpringAop_@around("pointcut()")-CSDN博客

2、【Spring】AOP进阶-JoinPoint和ProceedingJoinPoint详解_proceedingjoinpoint joinpoint-CSDN博客3

 3、重写Shiro,拦截RequiresPermissions权限标识获取逻辑,实现Controller多级权限拼接_requirespermissions 多个权限-CSDN博客

  • 20
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值