如何自定义注解应用在切面编程上?进阶高级程序员你需要懂!

回顾之前做了几个关于权限访问的功能,大家都会想到使用shiro进行处理,但是原生的提供的需要做适当的扩展才能满足自定义的权限控制,这时候,你就需要继承shiro的AuthorizingRealm类来实现
具体代码


@Component
public class HynRealmConfig extends AuthorizingRealm {

    @Autowired
    private RedisData redisData;

    @Autowired //用户权限
    private PermissionData permissionData;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof OAuth2Token;
    }
  
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        OAuth2Token loginToken=(OAuth2Token) token;
        if("app".equals(loginToken.getLoginChannel())
        	||"oa".equals(loginToken.getLoginChannel())
        	||"sso".equals(loginToken.getLoginChannel())
        	) {
        	return loginByApp(token);
        }else {
        	return loginDefault(token);
        }
    }
    
    private AuthenticationInfo loginDefault(AuthenticationToken token) throws AuthenticationException {
        OAuth2Token loginToken=(OAuth2Token) token;
        String accToken = loginToken.getPrincipal();
        
        //token失效,或首次登陆
        if (loginUser == null) {
            //首次登陆,账号密码登录
            if(StringUtils.isNotBlank(((OAuth2Token) token).getUserName())) {
                loginUser = userService.login(((OAuth2Token) token).getUserName(),((OAuth2Token) token).getPassword());
                if (!ObjectUtils.isEmpty(loginUser)&& !org.springframework.util.StringUtils.isEmpty(loginUser.getRemark())) {
                    throw new UnknownAccountException(loginUser.getRemark());
                }
                if (loginUser == null) {
                    throw new UnknownAccountException("账户不存在,请确认输入!");
                }

                if (loginUser.getDisabled()) {
                    throw new UnknownAccountException("账户被禁用!");
                }

                List<SysRoleDTO> roleList = userService.getRoleListByuserId(loginUser.getId());
                loginUser.setRoleList(roleList);
                Set<String> roleSet=new TreeSet<>();
                if(!CollectionUtils.isEmpty(roleList)) {
                    for (SysRoleDTO role : roleList) {
                        roleSet.add(role.getId());
                    }
                    //查询权限permission
                    Set<String> permissionSet= this.getPermissionList(roleSet);
                    if(!CollectionUtils.isEmpty(permissionSet)) {
                      
                    }

                }

                this.createToken(loginUser,accToken);
            }else {//token失效
                throw new NotAuthorizedException("token失效,请重新登录");
            }
        }
        return new SimpleAuthenticationInfo(loginUser.getId(),accToken,loginUser.getName());
    }

扩展了shiro的框架,就更好跟前端交互用户的权限以及那个返回的字段需要对其接口进行隐藏处理。那么下面就是后台利用自定义接口,以及自定义AOP进行对接口进行定义以及拦截。
自定义接口比较简单大致如下

@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ShiroAuth {
    String[] roles() default {};
    String permissions() default "";
    
}

可以设置用户的角色也可以设置权限列表,在接口上注释即可使用,那么使用的话,如何针对每个访问都可以实现拦截访问,答案就在于AOP进行处理,也是本文重点介绍的AOP编程
具体代码如下

@Component
@Aspect
@Order(110)
public class PermissionOperationAop {
    public final static int minLen=2;

    @Pointcut("@annotation(com.dream.annotation.ShiroAuth)")
    public void permissionCut(){
    }
    @Around("permissionCut()")
    public Object permissionOperation(ProceedingJoinPoint joinPoint) throws Throwable {
        Object proceed=null;
        MethodSignature sign = (MethodSignature)joinPoint.getSignature();
        Method method = sign.getMethod();
        ShiroAuth shiroAuth = method.getAnnotation(ShiroAuth.class);
        String permissions = shiroAuth.permissions();
        if(StringUtils.isBlank(permissions)){
            proceed = joinPoint.proceed();
            return proceed;
        }
        //判断是否有可操作的权限
        String[] nodes = permissions.split(":");
        String participant=null;
        String others=null;
        if(nodes.length<minLen){
            throw new IllegalArgumentException("@ShiroAuth中的权限标识格式不正确");
        }else if(nodes.length==minLen){
            participant=nodes[nodes.length-1];
        }else{
            participant=nodes[nodes.length-2];
            others=nodes[nodes.length-1];
        }

       Subject subject = SecurityUtils.getSubject();

        boolean checkDataScope = shiroAuth.checkDataScope();

        boolean permitted=false;
        if(checkDataScope){
            permitted = subject.isPermitted(new WildcardPermission(permissions));
        }

        String uid=(String)subject.getPrincipal();
        //获取被植入对象的参数列表
        Object[] args = joinPoint.getArgs();
        for(Object arg:args){
            if(arg instanceof BaseQuery){
                BaseQuery baseQuery=(BaseQuery) arg;
                baseQuery.setUid(uid);
                if(permitted){
                    baseQuery.setOperatorScope(BaseQuery.global);
                }
            }else if(arg instanceof BaseUpdate){
                BaseUpdate baseUpdate=(BaseUpdate) arg;
                baseUpdate.setUid(uid);
            }
        }
        proceed = joinPoint.proceed(args);
        return proceed;
    }

针对上面的代码核心部分进行重点的介绍
拦截的作用方法基于自定义接口 可以这样写

@Pointcut("@annotation(com.dream.annotation.ShiroAuth)")
    public void permissionCut(){
    }

以及拦截的方法作用的位置

@Around("permissionCut()")
    public Object permissionOperation(ProceedingJoinPoint joinPoint) throws Throwable

然后下面的代码块就是针对自定义好的字符串,也就是用户的权限进行处理判断,相信都可以很清晰明白如何使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值