spring aop实现用户权限管理的示例
aop 在实际项目中运用的场景主要有 权限管理(authority management)、事务管理(transaction management)、安全管理(security)、日志管理(logging)和调试管理(debugging) 等。
问题源于项目开发
最近项目中需要做一个权限管理模块,按照之前同事的做法是在controller层的每个接口调用之前上做逻辑判断,这样做也没有不妥,但是代码重复率太高,而且是体力劳动,so,便有了如题所说的使用spring aop做一个切点来实现通用功能的权限管理,这样也就降低了项目后期开发的可扩展性。
权限管理的代码实现与配置文件
在最小的代码修改程度上,aop无疑是最理想的选择。项目中有各种权限的复合,相对来说逻辑复杂度比较高,所以一步步来。因为权限涉及到的是后端接口的调用所以楼主选择在controller层代码做切面,而切点就是controller中的各个方法块,对于通用访问权限,我们使用execution表达式进行排除。
只读管理员权限的实现及切点选择
对于实现排除通用的controller,楼主采用的是execution表达式逻辑运算。因为只读管理员拥有全局读权限,而对于增删改权限,楼主采用的是使用切点切入是增删改的方法,so,这个时候规范的方法命名就很重要了。对于各种与只读管理员进行复合的各种管理员,我们在代码中做一下特殊判断即可。下面是spring aop的配置文件配置方法。
<bean id="userspermissionsadvice" class="com.thundersoft.metadata.aop.userspermissionsadvice"/> <aop:config> <!--定义切面 --> <aop:aspect id="authaspect" ref="userspermissionsadvice"> <!-- 定义切入点 (配置在com.thundersoft.metadata.web.controller下所有的类在调用之前都会被拦截) --> <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"/> <!--方法被调用之前执行的 --> <aop:before method="readonly" pointcut-ref="authpointcut"/> </aop:aspect> </aop:config>
只读管理员权限管理代码实现
上面说了那么多,废话不多说了,下面是对只读权限与各种复合权限进行控制的切面代码实现。
/** * 对只读管理员以及其复合管理员进行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; } /** * 只读管理员做数据更改权限的判断 */ 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全切,特殊情况在代码逻辑里面做实现即可。配置文件代码如下:
<aop:config> <!--定义切面 --> <aop:aspect id="authaspect" ref="userspermissionsadvice"> <!-- 定义切入点 (配置在com.thundersoft.metadata.web.controller下所有的类在调用之前都会被拦截) --> <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"/> <!--方法被调用之前执行的 --> <aop:before method="appdeptauth" pointcut-ref="appauthpointcut"/> </aop:aspect> </aop:config>
##权限管理的切面代码实现
/** * 对应用管理员以及部门管理员进行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; } /** * 应用管理员做数据更改权限的判断 */ 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; } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Sprint Boot 集成MongoDB的操作方法
下一篇: java编程实现两个大数相加代码示例