SpringBoot 数据权限新姿势,注解+动态SQL真香!


来自:网络,侵删

推荐一个程序员编程资料站:

http://cxyroad.com

副业赚钱专栏:https://xbt100.top

2024年IDEA最新激活方法

后台回复:激活码

CSDN免登录复制代码插件下载:

CSDN复制插件

以下是正文。


介绍

easy-data-scop 是一个通过动态注入SQL实现的数据权限项目。支持MyBatis、MyBatis-plus、MyBatis-flex。使用简单,无需设置各种复杂配置,仅仅通过注解便可实现效果功能。

基础项目搭建

1.数据库
图片
图片

这是一张简单的用户表,接下来我们将为这张表编写以下数据权限

  • 仅看id为1的人

  • 仅看年龄为111的人

  • 仅看年龄为222的人

  • 看年龄为111、222的人

2.导入依赖基础依赖 (使用MyBatis-plus、MyBatis XML演示)
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.2.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>2.2.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.3.0</version>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>8.0.33</version>
    </dependency>
</dependencies>
3.核心依赖
<dependency>
    <groupId>cn.zlinchuan</groupId>
    <artifactId>ds-mybatis</artifactId>
    <version>1.0.1</version>
</dependency>
4.启动类
@SpringBootApplication
publicclassMain{
    publicstaticvoidmain(String[] args){
        SpringApplication.run(Main.class);
    }
}
5.省略编写Mapper、Service
6.application.yml
server:
  port:8001
# DataSource Config
spring:
datasource:
    driver-class-name:com.mysql.cj.jdbc.Driver
    url:url
    username:name
    password:password
mybatis:
mapper-locations:classpath:mapper/*.xml# XML映射文件路径
mybatis-plus:
configuration:
    log-impl:org.apache.ibatis.logging.stdout.StdOutImpl
7.测试
@Autowired
private UserService userService;

@Test
publicvoidtest(){
    
    userService.getAll().forEach(System.out::println);
}
图片
图片

到这里项目就已经搭建完成了

使用 easy-data-scope

图片
图片

实现核心接口DataScopeFindRule 并交由Spring管理

图片
图片
easy-data-scope` 会去代理 `@DataScope` 方法调用 `find()` 获取到 `DataScopeInfo
DataScopeInfo介绍

easy-data-scope 会根据 find() 方法返回的 DataScopeInfo 列表来构建SQL

图片
图片
@DataScope介绍

可以编写在对应需要数据权限拦截的方法上

属性:

public@interface DataScope {
    /**
     * 通过传递给DataScopeFindRule.find方法来获取指定的数据权限实体
     * @return
     */
    String[] keys();

    /**
     * 构建模板
     * TODO 注意:当key为多个时此值生效
     * key1 ==SQL==> table1.column1 = 1
     * key2 ==SQL==> table2.column2 = 2
     * 示例:template = "{key1} OR {key2}"
     * 通过template生成后的SQL:table1.column1 = 1 OR table2.column2 = 2
     * @return
     */
    String template()default "";

    /**
     * 是否对数据权限进行自动合并
     * 当操作符为 =、!= 时间如果TableName、ColumnName、操作符一样,并且使用的是 Value 形式将会对数据权限进行合并为 IN、NOT IN
     * 示例:
     * 权限1:=、table1、column1、Value1 >>> table1.column1 = Value1
     * 权限2:=、table1、column1、Value2 >>> table1.column1 = Value2
     * 最终合并 in table1、column1、“Value1, Value2" >>> table1.column1 in (Value1, Value2)
     * @return
     */
    booleanmerge()defaultfalse;

    /**
     * 逻辑符
     * 决定数据权限SQL拼接到当前执行的SQL中用的使用的是 WHERE还是AND还是OR..
     * TODO 注意:在flag为true时此值将会失效
     * @return
     */
    String logical()default SqlConsts.AND;

    /**
     * 是否使用数据权限标记位标记位,true是 false否
     * @return
     */
    booleanflag()defaultfalse;
}
图片
图片

实现前文的数据权限

编写DataScopeFindRule find 方法

@Override
public List<DataScopeInfo> find(String[] key){
    // 模拟的用户登陆Session
    UserSessionInfo userSession = UserSessionContext.getUserSession();
    if (userSession != null) {
        // 数据库中查询
        QueryWrapper<AuthDatascopeEntity> idQueryWrapper = new QueryWrapper<>();
        // 查询用户Session中保存用户有哪些数据权限
        idQueryWrapper.in("id", userSession.getDataScopeIds());
        idQueryWrapper.in("datascope_key", key);
        List<AuthDatascopeEntity> authDatascopes = authDataSocpeMapper.selectList(idQueryWrapper);
        // 构建出DataScopeInfo
        List<DataScopeInfo> dataScopeInfos = new ArrayList<>(authDatascopes.size());
        for (AuthDatascopeEntity authDatascope : authDatascopes) {
            DataScopeInfo dataScopeInfo = new DataScopeInfo();
            dataScopeInfo.setKey(authDatascope.getDatascopeKey());
            dataScopeInfo.setOperator(authDatascope.getDatascopeOpName());
            dataScopeInfo.setTableName(authDatascope.getDatascopeTbName());
            dataScopeInfo.setColumnName(authDatascope.getDatascopeColName());
            dataScopeInfo.setSql(authDatascope.getDatascopeSql());
            dataScopeInfo.setValue(authDatascope.getDatascopeValue());
            dataScopeInfo.setSort(authDatascope.getDatascopeSort());
            dataScopeInfos.add(dataScopeInfo);
        }
        return dataScopeInfos;
    }

    return Collections.emptyList();
}
创建数据权限表
-- auto-generated definition
createtable auth_datascope
(
    id                 int auto_increment comment'编号'
        primary key ,
    datascope_key      varchar(200)  nullcomment'数据权限标识' ,
    datascope_name     varchar(200)  nullcomment'数据权限名称' ,
    datascope_tb_name  varchar(500)  nullcomment'数据权限表别名' ,
    datascope_col_name varchar(500)  nullcomment'数据权限字段名' ,
    datascope_op_name  varchar(10)   nullcomment'数据权限操作符' ,
    datascope_sql      varchar(5000) nullcomment'数据权限sql' ,
    datascope_value    varchar(200)  nullcomment'数据权限值' ,
    datascope_sort     int           nullcomment'数据权限排序' ,
    datascope_des      varchar(500)  nullcomment'数据权限描述'
)
    comment'数据权限表';

1.只看Id为1的记录

图片
图片

将对应实体添加到库中,实现动态配置

编写Service

@DataScope(keys = "USER_LIST_ID", logical = SqlConsts.WHERE)
public List<UserEntity> getAll(){
    return userMapper.selectList(null);
}

调用后得到结果

SELECTid,username,age FROMuserWHERE ( user.id = 1)

2.仅看年龄为111的人

图片
图片
@DataScope(keys = "USER_LIST_AGE111", logical = SqlConsts.WHERE)
public List<UserEntity> getAll2(){
    return userMapper.selectList(null);
}

调用后得到结果

SELECTid,username,age FROMuserWHERE ( user.age = 111)

3.仅看年龄为222的人

图片
图片
@DataScope(keys = "USER_LIST_AGE222", logical = SqlConsts.WHERE)
public List<UserEntity> getAll3(){
    return userMapper.selectList(null);
}

调用后得到结果

SELECTid,username,age FROMuserWHERE ( user.age = 222)

4.看年龄为111、222的人(merge属性)

其他的不用动,使用注解中的 merge 属性,在keys中将两个前两个key都加上

@DataScope(keys = {"USER_LIST_AGE111", "USER_LIST_AGE222"}, merge = true, logical = SqlConsts.WHERE)
public List<UserEntity> getAll4(){
    return userMapper.selectList(null);
}

调用后得到结果

SELECTid,username,age FROMuserWHERE ( user.age IN (111, 222))

更多操作

@DataScope.flag

Mapper.xml

@DataScope(keys = {"USER_LIST_AGE111", "USER_LIST_AGE222"}, merge = true, flag = true)
List<UserEntity> getAll5();
<selectid="getAll5"resultType="cn.zlinchuan.entity.UserEntity">
    select * from (select * from user where {{_DATA_SCOPE_FLAG}}) t where 1 = 1
</select>

注意 {{_DATA_SCOPE_FLAG}} 为程序定义占位,不能修改

sql

select * from (select * fromuserwhere user.age IN (111, 222)) t where1 = 1
@DataScope.template
@DataScope(keys = {"USER_LIST_AGE111", "USER_LIST_AGE222"}, flag = true, template = "{{USER_LIST_AGE111}} OR {{USER_LIST_AGE222}}")
List<UserEntity> getAll6();
<selectid="getAll6"resultType="cn.zlinchuan.entity.UserEntity">
    select * from (select * from user where {{_DATA_SCOPE_FLAG}}) t where 1 = 1
</select>

sql

select * from (select * fromuserwhere user.age = 111OR user.age = 222) t where1 = 1

项目源码地址

https://github.com/zoulinchuan/easy-data-scope

<END>

推荐阅读:

副业赚钱推荐:让你的时间开始变现!

免费体验AI图片生成,就在 Image Generator Hub!

程序员在线工具站:cxytools.com
推荐一个自己写的工具站:https://cxytools.com,专为程序员设计,包括时间日期、
JSON处理、SQL格式化、随机字符串生成、UUID生成、文本Hash...等功能,提升开发效
率。
⬇戳阅读原文直达!                                  朕已阅
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值