▶背景:
需要在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; } }