▶背景:

  需要在springboot项目里面用到shiro的权限管理,Shiro访问控制流程:先shiro认证(登录时调用) 然后 shiro授权,但是项目里面登录的功能用的公司统一的系统,所以需要“绕过”shiro认证,

  解决方式是:在用户访问需要鉴权的接口之前,通过硬编码的方式进行shiro认证。

 

▶使用@RequiresPermissions("sys:user:shiro"):

  在指定接口上面添加@RequiresPermissions("sys:user:shiro")进行权限控制会进行shiro授权若有进行shiro认证(登录),流程为: 依次调用@Aspect切面类(如果有定义) ==>shiro授权==>目标方法。

  若无shiro认证(登录),则直接报错目前(2020/12/03)还没有找到使用使用@RequiresPermissions注解并且可以“绕过”shiro认证的方法,所以暂时放弃使用此注解。

 

▶不使用@RequiresPermissions("sys:user:shiro"):

  如果不使用@RequiresPermissions注解,麻烦点的方式就是直接硬编码,在每个需要权限管理的接口里面硬编码会造成代码冗余,所以选择了配置@Aspect切面类,在满足的 切入点Pointcut 表达式中的方法

  执行前增加自定义验证逻辑,符合条件则继续执行,否则终止目标接口的执行,代码如下。

@Aspect
@Component
@Order(value = 3)
public class ShiroAuthenticationAspect {
    private static final Logger logger = LoggerFactory.getLogger(ShiroAuthenticationAspect.class);

    @Pointcut("execution(public  * cn.wj.fdata.console.controller.AuthorityManagementController.*(..) )")
    public void controllerPointcut() {
    }

    @Around("controllerPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        Object ret = null;
        String userName = getLoginUid(request);
        logger.info("loginName="+userName);
        try{
            // 自定义验证逻辑,符合条件则继续执行,否则终止方法的执行
            // 1、进行Shiro认证(登录)
            Subject subject = ShiroUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(userName, "");
            subject.login(token);
            logger.info("登录成功");

            boolean permitted = subject.isPermitted("sys:user:shiroAA");
            if(permitted){ // 2、有对应权限则执行方法
                ret = joinPoint.proceed();
                logger.info("{}环绕proceed,结果是 :{}" , request.getRequestURL(), ret);
            }else{
                logger.info("{}环绕proceed,不满足条件未执行",request.getRequestURL());
                Message<Object> message = new Message<Object>();
                message.setCode(FdataConstants.EXECUTE_USER_NOPOWER_ERROR);
                message.setMsg("无操作权限!");
                ret = message;
            }
        }catch (Throwable e) {
            logger.error("error", e);
        }
        return ret;
    }

    private String getLoginUid(HttpServletRequest request) {
        Object attribute = request.getAttribute("fsmart.login.uid");
        return (String)attribute;
    }
}

 

  

posted on 2020-12-03 15:39  半纸情书  阅读(5232)  评论(0编辑  收藏  举报