若依ruoyiAOP切面用于数据过滤和权限处理实例
目录
1.什么是AOP
简介
2.若依的AOP实现
2.1若依数据过滤AOP
定义注解
实现切面类
2.2数据源AOP
1.什么是AOP
简介
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术,是Spring的三大核心思想之一。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
换句话说,浅显的理解就是在项目中横切一刀,放置一个过滤网来拦截数据或实现代码复用。
原先的项目
实现代码复用,减少代码量,但是需要不断引入和配置。
实现AOP,切入过程中,既实现了代码复用,也将模块完成独立出来,减少了工作量详情参看大佬文章【SpringBoot-3】切面AOP实现权限校验:实例演示与注解全解_云深i不知处的博客-CSDN博客
2.若依的AOP实现
简单介绍一下若依的AOP使用
引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2.1若依数据过滤AOP
定义注解
/*** 数据权限过滤注解* * @author ruoyi*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataScope
{/*** 部门表的别名*/public String deptAlias() default "";/*** 用户表的别名*/public String userAlias() default "";
}
@DataScope,用于数据过滤的注解,有两个参数默认为“ ”,这两个参数可以用于不同表的数据过滤,可以根据自己需求添加多个参数
有三个注解实现配置
@Target 用于描述注解的使用范围,被描述的注解可以用在什么地方,参数
@Retention 用于定义注解的生命周期,参数
SOURCE | 在源文件中有效(即源文件保留) |
---|---|
CLASS | 在class文件中有效(即class保留) |
RUNTIME | 在运行时有效(即运行时保留) |
@Document 用于标注生成javadoc的时候是否会被记录。
实现切面类
一步一步来看
先定义切面类
*** 数据过滤处理* * @author ruoyi*/
@Aspect
@Component
public class DataScopeAspect
@Aspect 用于表示该类为切面类 @Component 组件加入容器中
@Before("@annotation(controllerDataScope)")public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable{clearDataScope(point);handleDataScope(point, controllerDataScope);}
@Before 用于定义方法,该方法在切面切入目标方法之前执行
参数 JoinPoint:该对象封装了SpringAOP中切面方法的信息,可以获取到封装了该方法信息的JoinPoint对象。
参数 DataScope 注解对象,包含注解填入的两个参数
该方法先调用了clearDataScope()方法
/*** 拼接权限sql前先清空params.dataScope参数防止注入*/private void clearDataScope(final JoinPoint joinPoint){Object params = joinPoint.getArgs()[0];if (StringUtils.isNotNull(params) && params instanceof BaseEntity){BaseEntity baseEntity = (BaseEntity) params;baseEntity.getParams().put(DATA_SCOPE, "");}}
作用就是清空params.DATA_SCOPE参数防止注入,DATA_SCOPE是请求经过AOP切面后被放入的参数,用于在sql语句中的数据过滤,所以需要清空,以免sql注入,虽然可能性不大
后调用handleDataScope()方法
protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope){// 获取当前的用户SysUser currentUser = ShiroUtils.getSysUser();if (currentUser != null){// 如果是超级管理员,则不过滤数据if (!currentUser.isAdmin()){dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),controllerDataScope.userAlias());}}
可以看出,如果请求中包含用户信息而且不为管理员才可以进行数据的过滤
方法dataScopeFilter()才是逻辑的主要部分
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias){StringBuilder sqlString = new StringBuilder();for (SysRole role : user.getRoles()){String dataScope = role.getDataScope();if (DATA_SCOPE_ALL.equals(dataScope)){sqlString = new StringBuilder();break;}else if (DATA_SCOPE_CUSTOM.equals(dataScope)){sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,role.getRoleId()));}else if (DATA_SCOPE_DEPT.equals(dataScope)){sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));}else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)){sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",deptAlias, user.getDeptId(), user.getDeptId()));}else if (DATA_SCOPE_SELF.equals(dataScope)){if (StringUtils.isNotBlank(userAlias)){sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));}else{// 数据权限为仅本人且没有userAlias别名不查询任何数据sqlString.append(" OR 1=0 ");}}}
逻辑很简单,用请求中的dataScope值(数据库查询出的值)来判断该用户拥有哪种权限
然后根据@DataScope注解的值,来判断这个用户正在访问哪张表,此时就可以将一段字符串放入sqlString中
if (StringUtils.isNotBlank(sqlString.toString())){Object params = joinPoint.getArgs()[0];if (StringUtils.isNotNull(params) && params instanceof BaseEntity){BaseEntity baseEntity = (BaseEntity) params;baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");}}
如果sqlString不为空,且被注解定义的方法的参数继承了BaseEntity(Entity基类
)就将sqlString放入参数中
最后,将@DataScope注解放在Servcie层的方法上
@DataScope(deptAlias = "aaa")public List selectList(Params param){return Mapper.selectList(param);}
在Mapper中添加
${params.dataScope}
动态sql注入
2.2数据源AOP
若依ruoyiAOP切面用于数据过滤和权限处理实例相关推荐
- 驳斥《沙盒用于数据防泄密是重大技术原理性失误》
驳斥<沙盒用于数据防泄密是重大技术原理性失误> 最近网上出现了一篇名为<沙盒用于数据防泄密是重大技术原理性失误>的文章,经作者鉴定,是某不良公司***技术领先的竞争对手苏州深信 ...
- 通用数据级别权限的框架设计与实现(3)-数据列表的权限过滤
查看上篇文章通用数据级别权限的框架设计与实现(2)-数据权限的准备工作,我们开始数据列表的权限过滤. 原理:我们在做过滤列表时,根据用户权限自动注入到相关SQL中,实现相关过滤,如果拥有全部权限,则不 ...
- 【Android 内存优化】Android 工程中使用 libjpeg-turbo 压缩图片 ( JNI 传递 Bitmap | 获取位图信息 | 获取图像数据 | 图像数据过滤 | 释放资源 )
文章目录 一.Bitmap 图像数据处理 二.Java 层 Bitmap 对象转为 JNI 层 bitmap 对象 三.获取 bitmap 中的图像数据 四.过滤 bitmap 中的图像数据 ( 获取 ...
- Aspose Cells 控件如何实现数据过滤(附代码和下载地址)
Aspose Cells 是一款操作和处理以及转换Excel文件的类库,支持.NET和JAVA版,几乎所有Excel能实现的功能,Aspose Cells都可以实现,在Excel中经常会用到数据过滤, ...
- Hibernate的数据过滤查询
数据过滤并不是一种常规的数据查询方法,而是一种整体的筛选方法.数据过滤也可对数据进行筛选,因此,将其放在Hibernate的数据查询框架中介绍. 如果一旦启用了数据过滤器,则不管数据查询,还是数据加载 ...
- .NET WinForm程序中给DataGridView表头添加下拉列表实现数据过滤
转:http://www.cnblogs.com/jaxu/archive/2011/08/04/2127365.html 我们见过Excel中的数据过滤功能,可以通过点击表头上的下拉列表来实现数据的 ...
- 云小课|聊一聊DRS的数据过滤特性
[本期推荐专题]在DevOps市场中,华为云DevCloud拔得头筹,看它如何助力企业面对商业环境瞬息万变快速响应. [摘要] 目前,DRS已支持其他云.本地IDC.ECS自建MySQL.SQL Se ...
- 【SQL必知必会笔记(3)】SELECT语句的WHERE子句数据过滤操作
上个笔记主要介绍了利用SELECT语句检索单个/多个/所有列,并利用DISTINCT关键字检索具有唯一性的值.利用LIMIT/OFFSET子句限制结果:以及利用ORDER BY子句排序检索出的数据,主 ...
- Ruo-Yi前后端分离的数据过滤
Ruo-Yi前后端分离的数据过滤 若依官网的介绍:http://doc.ruoyi.vip/ruoyi/document/htsc.html#%E6%95%B0%E6%8D%AE%E6%9D%83%E ...
最新文章
- 浅谈pytorch 模型 .pt, .pth, .pkl的区别及模型保存方式 pth中的路径加载使用
- 静态联编与动态联编之virtual的作用
- 双轮摩托车模安装测试
- [bzoj 3534][Sdoi2014] 重建
- CSS特效(1)——css伪类实现表单验证样式
- 《JAVA与模式》之合成模式
- linux系统服务总结之五:用lamp建一个自己的BBS(LINUX环境下)
- 开源高性能RISC-V处理器“香山”问世
- 超级终端软件测试工程师,超级终端是否可用来测试 RS485?
- vbox 按照增强工具 centos7
- 时间管理术第一原则总结
- 浅谈语音识别技术的发展趋势与应用前景
- 精通ASP.NET Web程序测试
- java解析varbinary_java – JdbcTemplate:以字符串形式访问MySQL VARBINARY字段
- php 爬网页数据 入库,phpspider是一个基于QueryList3的数据PHP爬虫,页面深度爬取,超简单的使用...
- Linux 访问 Windows 代理服务器配置
- 计算机网络出行711,出现网络连接711五种解决方法详解
- cesium中长度测量和面积测量
- 【深度学习】ResNet系列网络结构
- 关于人生的一些想法,和淘客SEO的思想。