spring aop实现权限管理
问题源于项目开发
最近项目中需要做一个权限管理模块,按照之前同事的做法是在controller层的每个接口调用之前上做逻辑判断,这样做也没有不妥,但是代码重复率太高,而且是体力劳动,so,便有了如题所说的使用spring aop做一个切点来实现通用功能的权限管理,这样也就降低了项目后期开发的可扩展性。
权限管理的代码实现与配置文件
在最小的代码修改程度上,aop无疑是最理想的选择。项目中有各种权限的复合,相对来说逻辑复杂度比较高,所以一步步来。因为权限涉及到的是后端接口的调用所以楼主选择在controller层代码做切面,而切点就是controller中的各个方法块,对于通用访问权限,我们使用execution表达式进行排除。
只读管理员权限的实现及切点选择
对于实现排除通用的controller,楼主采用的是execution表达式逻辑运算。因为只读管理员拥有全局读权限,而对于增删改权限,楼主采用的是使用切点切入是增删改的方法,so,这个时候规范的方法命名就很重要了。对于各种与只读管理员进行复合的各种管理员,我们在代码中做一下特殊判断即可。下面是spring aop的配置文件配置方法。
<!--非法权限抛出异常的spring mvc的处理-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="com.thundersoft.metadata.exception.AccessDeniedException">forward:/auth/readOnly</prop>
</props>
</property>
</bean>
<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)) {
if (methodName.contains("redirectToLogout")) {
return;
}
logger.error("只读管理员无操作权限!");
throw new AccessDeniedException("您无权操作!");
}
/**
* 部门管理员,且为只读管理员,
*/
if (PermissionsLabeled.dept_reader_Admin.equals(roleFlag)) {
if (object instanceof DepartmentController) {
return;
}
if (object instanceof UserController) {
if (methodName.contains("addAdmin")) {
throw new AccessDeniedException("您无权操作!");
}
if (methodName.contains("deleteAdmin")) {
throw new AccessDeniedException("您无权操作!");
}
if (methodName.contains("updateAdmin")) {
throw new AccessDeniedException("您无权操作!");
}
return;
}
if (object instanceof GroupController) {
return;
}
logger.error("部门管理员,且为只读管理员无操作权限!");
throw new AccessDeniedException("您无权操作!");
}
/**
* 应用管理员,且为只读管理员
*/
if (PermissionsLabeled.app_reader_Admin.equals(roleFlag)) {
if (object instanceof AppController) {
return;
}
if (object instanceof AppPolicyController) {
return;
}
logger.error("应用管理员,且为只读管理员无操作权限!");
throw new AccessDeniedException("您无权操作!");
}
/**
* 部门管理员,且为应用管理员,且为只读管理员
*/
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("部门管理员,且为应用管理员,且为只读管理员无操作权限");
throw new AccessDeniedException("您无权操作!");
}
}
具有专门功能的管理员权限控制的切点选择
因为具有专门的管理员权限比较特殊,楼主采用的方式除了通用访问权限之外的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("应用管理员无操作权限");
throw new AccessDeniedException("您无权操作!");
} 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("应用管理员无操作权限");
throw new AccessDeniedException("您无权操作!");
} else {
return;
}
}
自定义权限非法异常代码
/**
* @author wuhf0703@thundersoft.com
* @date 2017/12/12
*/
public class AccessDeniedException extends RuntimeException {
/**
* Constructs a <code>AccessDeniedException</code> with the specified message.
*
* @param msg the detail message.
*/
public AccessDeniedException(String msg) {
super(msg);
}
/**
* Constructs a {@code AccessDeniedException} with the specified message and root cause.
*
* @param msg the detail message.
* @param t root cause
*/
public AccessDeniedException(String msg, Throwable t) {
super(msg, t);
}
}
spring aop实现权限管理的更多相关文章
- (39.3) Spring Boot Shiro权限管理【从零开始学Spring Boot】
在学习此小节之前您可能还需要学习: (39.1) Spring Boot Shiro权限管理[从零开始学Spring Boot] http://412887952-qq-com.iteye.com/b ...
- (39.2). Spring Boot Shiro权限管理【从零开始学Spring Boot】
(本节提供源代码,在最下面可以下载) (4). 集成Shiro 进行用户授权 在看此小节前,您可能需要先看: http://412887952-qq-com.iteye.com/blog/229973 ...
- (39.1) Spring Boot Shiro权限管理【从零开始学Spring Boot】
(本节提供源代码,在最下面可以下载)距上一个章节过了二个星期了,最近时间也是比较紧,一直没有时间可以写博客,今天难得有点时间,就说说Spring Boot如何集成Shiro吧.这个章节会比较复杂,牵涉 ...
- Spring Boot Shiro 权限管理
Spring Boot Shiro 权限管理 标签: springshiro 2016-01-14 23:44 94587人阅读 评论(60) 收藏 举报 .embody{ padding:10px ...
- 使用Spring Security实现权限管理
使用Spring Security实现权限管理 1.技术目标 了解并创建Security框架所需数据表 为项目添加Spring Security框架 掌握Security框架配置 应用Security ...
- (39.4) Spring Boot Shiro权限管理【从零开始学Spring Boot】
在读此文章之前您还可能需要先了解: (39.1) Spring Boot Shiro权限管理[从零开始学Spring Boot] http://412887952-qq-com.iteye.com/b ...
- 十、 Spring Boot Shiro 权限管理
使用Shiro之前用在spring MVC中,是通过XML文件进行配置. 将Shiro应用到Spring Boot中,本地已经完成了SpringBoot使用Shiro的实例,将配置方法共享一下. 先简 ...
- Spring Boot Shiro 权限管理 【转】
http://blog.csdn.net/catoop/article/details/50520958 主要用于备忘 本来是打算接着写关于数据库方面,集成MyBatis的,刚好赶上朋友问到Shiro ...
- springBoot整合spring security实现权限管理(单体应用版)--筑基初期
写在前面 在前面的学习当中,我们对spring security有了一个小小的认识,接下来我们整合目前的主流框架springBoot,实现权限的管理. 在这之前,假定你已经了解了基于资源的权限管理模型 ...
随机推荐
- GMT时间
GMT:格林尼标准时间 北京时间=GMT时间+8小时
- 四、Jmeter--参数化
一.CSV 参数化 1.我们做性能测试需要并发多个用户,为了真实模拟用户行为,我们需要模拟多个不同的用户登录,这是我们就需要进行参数化.这里我们选择比较常用的参数化方法-CSV Data Set Co ...
- MongoDb学习网站
http://www.runoob.com/mongodb/mongodb-window-install.html
- openwrt: Makefile 框架分析[转载]
openwrt目录结构 上图是openwrt目录结构,其中第一行是原始目录,第二行是编译过程中生成的目录.各目录的作用是: tools - 编译时需要一些工具, tools里包含了获取和编译这些工具的 ...
- java代码继承------多层继承
总结:继承.方法的重要性, 运行结果显示: class A is callingclass B is callingclass C is calling package com.addd; //jav ...
- Oracle Flushback 学习测试
Oracle Flushback 学习测试:三思笔记 Flashback恢复 从9i开始,利用oracle查询的多版本一致的特点,实现从回滚段中读取一定时间内在表中操作的数据,被称为 flashbac ...
- Jlink flash 烧录HEX 程序
一般Jlink版本 和 Jag(硬件)最好匹配 安装Jlink 时,IAR的工具包也可以顺带安装. 有源码: IAR 可以自动选择CPU型号,代码直接Download and debug https: ...
- Linux系统下Oracle执行SQL脚本后中文出现乱码解决方法
先确认Oracle的字符集,sqlplus登录Oracle后执行语句: [sql] select userenv('language') from dual; 返回值例如:AMERICAN_AME ...
- 记录一次手机联系人整理(XML文件格式处理)
场景:1.IOS手机和Android手机联系人同步时有部分重复联系人. 2.很早以前的HTC手机导出的联系人中备注信息有大量乱码,且很多联系人生日被设置为1970-01-01,导致生日提醒软件产生骚扰 ...
- springmvc urlpattern配置详解
静态资源无法访问问题的解决方案: 1.使用Tomcat默认的Servlet解决:在web.xml中加以下代码