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