spring aop實現(xiàn)用戶權限管理的示例
AOP 在實際項目中運用的場景主要有 權限管理(Authority Management)、事務管理(Transaction Management)、安全管理(Security)、日志管理(Logging)和調(diào)試管理(Debugging) 等。
問題源于項目開發(fā)
最近項目中需要做一個權限管理模塊,按照之前同事的做法是在controller層的每個接口調(diào)用之前上做邏輯判斷,這樣做也沒有不妥,但是代碼重復率太高,而且是體力勞動,so,便有了如題所說的使用spring aop做一個切點來實現(xiàn)通用功能的權限管理,這樣也就降低了項目后期開發(fā)的可擴展性。
權限管理的代碼實現(xiàn)與配置文件
在最小的代碼修改程度上,aop無疑是最理想的選擇。項目中有各種權限的復合,相對來說邏輯復雜度比較高,所以一步步來。因為權限涉及到的是后端接口的調(diào)用所以樓主選擇在controller層代碼做切面,而切點就是controller中的各個方法塊,對于通用訪問權限,我們使用execution表達式進行排除。
只讀管理員權限的實現(xiàn)及切點選擇
對于實現(xiàn)排除通用的controller,樓主采用的是execution表達式邏輯運算。因為只讀管理員擁有全局讀權限,而對于增刪改權限,樓主采用的是使用切點切入是增刪改的方法,so,這個時候規(guī)范的方法命名就很重要了。對于各種與只讀管理員進行復合的各種管理員,我們在代碼中做一下特殊判斷即可。下面是spring aop的配置文件配置方法。
<bean id="usersPermissionsAdvice" class="com.thundersoft.metadata.aop.UsersPermissionsAdvice"/> <aop:config> <!--定義切面 --> <aop:aspect id="authAspect" ref="usersPermissionsAdvice"> <!-- 定義切入點 (配置在com.thundersoft.metadata.web.controller下所有的類在調(diào)用之前都會被攔截) --> <aop:pointcut expression="(execution(* com.thundersoft.metadata.web.controller.*.add*(..)) or execution(* com.thundersoft.metadata.web.controller.*.edit*(..)) or execution(* com.thundersoft.metadata.web.controller.*.del*(..)) or execution(* com.thundersoft.metadata.web.controller.*.update*(..)) or execution(* com.thundersoft.metadata.web.controller.*.insert*(..)) or execution(* com.thundersoft.metadata.web.controller.*.modif*(..))) or execution(* com.thundersoft.metadata.web.controller.*.down*(..))) and ( !execution(* com.thundersoft.metadata.web.controller.FindPasswordController.*(..)) and !execution(* com.thundersoft.metadata.web.controller.SelfServiceController.*(..)) and !execution(* com.thundersoft.metadata.web.controller.HomeController.*(..)) and !execution(* com.thundersoft.metadata.web.controller.UserStatusController.*(..)) and !execution(* com.thundersoft.metadata.web.controller.DashboardController.*(..)) and !execution(* com.thundersoft.metadata.web.controller.MainController.*(..))))" id="authPointCut"/> <!--方法被調(diào)用之前執(zhí)行的 --> <aop:before method="readOnly" pointcut-ref="authPointCut"/> </aop:aspect> </aop:config>
只讀管理員權限管理代碼實現(xiàn)
上面說了那么多,廢話不多說了,下面是對只讀權限與各種復合權限進行控制的切面代碼實現(xiàn)。
/** * 對只讀管理員以及其復合管理員進行aop攔截判斷. * @param joinPoint 切入點. * @throws IOException */ public void readOnly(JoinPoint joinPoint) throws IOException { /** * 獲取被攔截的方法. */ String methodName = joinPoint.getSignature().getName(); /** * 獲取被攔截的對象. */ Object object = joinPoint.getTarget(); logger.info("權限管理aop,方法名稱" + methodName); HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); HttpServletResponse response =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); String roleFlag = GetLoginUserInfor.getLoginUserRole(request); /** * 超級管理員 */ if (PermissionsLabeled.super_Admin.equals(roleFlag)) { return; } /** * 只讀管理員做數(shù)據(jù)更改權限的判斷 */ if (PermissionsLabeled.reader_Admin.equals(roleFlag)) { logger.error("只讀管理員無操作權限!"); response.sendRedirect(request.getContextPath() + "/auth/readOnly"); } /** * 部門管理員,且為只讀管理員, */ if (PermissionsLabeled.dept_reader_Admin.equals(roleFlag)) { if (object instanceof DepartmentController) { return; } if (object instanceof UserController) { if (methodName.contains("addAdmin")) { response.sendRedirect(request.getContextPath() + "/auth/readOnly"); } if (methodName.contains("deleteAdmin")) { response.sendRedirect(request.getContextPath() + "/auth/readOnly"); } if (methodName.contains("updateAdmin")) { response.sendRedirect(request.getContextPath() + "/auth/readOnly"); } return; } if (object instanceof GroupController) { return; } logger.error("部門管理員,且為只讀管理員無操作權限!"); response.sendRedirect(request.getContextPath() + "/auth/readOnly"); } /** * 應用管理員,且為只讀管理員 */ if (PermissionsLabeled.app_reader_Admin.equals(roleFlag)) { if (object instanceof AppController) { return; } if (object instanceof AppPolicyController) { return; } logger.error("應用管理員,且為只讀管理員無操作權限!"); response.sendRedirect(request.getContextPath() + "/auth/readOnly"); } /** * 部門管理員,且為應用管理員,且為只讀管理員 */ if (PermissionsLabeled.dept_app_reader_Admin.equals(roleFlag)) { if (object instanceof DepartmentController) { return; } if (object instanceof UserController) { return; } if (object instanceof GroupController) { return; } if (object instanceof AppController) { return; } if (object instanceof AppPolicyController) { return; } logger.error("部門管理員,且為應用管理員,且為只讀管理員無操作權限"); response.sendRedirect(request.getContextPath() + "/auth/readOnly"); } }
具有專門功能的管理員權限控制的切點選擇
因為具有專門的管理員權限比較特殊,樓主采用的方式除了通用訪問權限之外的controller全切,特殊情況在代碼邏輯里面做實現(xiàn)即可。配置文件代碼如下:
<aop:config> <!--定義切面 --> <aop:aspect id="authAspect" ref="usersPermissionsAdvice"> <!-- 定義切入點 (配置在com.thundersoft.metadata.web.controller下所有的類在調(diào)用之前都會被攔截) --> <aop:pointcut expression="(execution(* com.thundersoft.metadata.web.controller.*.*(..)) and ( !execution(* com.thundersoft.metadata.web.controller.FindPasswordController.*(..)) and !execution(* com.thundersoft.metadata.web.controller.SelfServiceController.*(..)) and !execution(* com.thundersoft.metadata.web.controller.HomeController.*(..)) and !execution(* com.thundersoft.metadata.web.controller.UserStatusController.*(..)) and !execution(* com.thundersoft.metadata.web.controller.DashboardController.*(..)) and !execution(* com.thundersoft.metadata.web.controller.MainController.*(..))))" id="appAuthPointCut"/> <!--方法被調(diào)用之前執(zhí)行的 --> <aop:before method="appDeptAuth" pointcut-ref="appAuthPointCut"/> </aop:aspect> </aop:config>
##權限管理的切面代碼實現(xiàn)
/** * 對應用管理員以及部門管理員進行aop攔截判斷. * @param joinPoint 切入點. * @throws IOException */ public void appDeptAuth(JoinPoint joinPoint) throws IOException { /** * 獲取被攔截的方法. */ String methodName = joinPoint.getSignature().getName(); /** * 獲取被攔截的對象. */ Object object = joinPoint.getTarget(); logger.info("權限管理aop,方法名稱",methodName); HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); HttpServletResponse response =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); String roleFlag = GetLoginUserInfor.getLoginUserRole(request); /** * 超級管理員 */ if (PermissionsLabeled.super_Admin.equals(roleFlag)) { return; } /** * 應用管理員做數(shù)據(jù)更改權限的判斷 */ if (PermissionsLabeled.app_Admin.equals(roleFlag)) { if (object instanceof AppController) { return; } if (object instanceof AppPolicyController) { return; } logger.error("應用管理員無操作權限"); response.sendRedirect(request.getContextPath() + "/auth/readOnly"); } else if (PermissionsLabeled.dept_Admin.equals(roleFlag)) { if (object instanceof DepartmentController) { return; } if (object instanceof UserController) { return; } if (object instanceof GroupController) { return; } if ("getAllDepartments".equals(methodName)) { return; } logger.error("應用管理員無操作權限"); response.sendRedirect(request.getContextPath() + "/auth/readOnly"); } else { return; } }
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Java MultipartFile實現(xiàn)上傳文件/上傳圖片
這篇文章主要介紹了Java MultipartFile實現(xiàn)上傳文件/上傳圖片,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-12-12SpringCloud?Alibaba環(huán)境集成之nacos詳解
Spring?Cloud?Alibaba提供了越來越完善的各類微服務治理組件,比如分布式服務配置與注冊中心nacos,服務限流、熔斷組件sentinel等,本篇先來介紹SpringCloud?Alibaba環(huán)境集成之nacos詳解,需要的朋友可以參考下2023-03-03feign參數(shù)過多導致調(diào)用失敗的解決方案
這篇文章主要介紹了feign參數(shù)過多導致調(diào)用失敗的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03如何使用Idea搭建全注解式開發(fā)的SpringMVC項目
這篇文章主要介紹了如何使用Idea搭建全注解式開發(fā)的SpringMVC項目,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03java 中動態(tài)代理(JDK,cglib)實例代碼
這篇文章主要介紹了java 中動態(tài)代理,這里介紹了JDK 動態(tài)代理與 cglib 動態(tài)代理的相關資料2017-04-04