今天来聊一聊大型SaaS系统的数据范围权限设计与实现.

  • 前言

  • 数据库设计

  • 引入依赖

  • 实现

前言

多租户(Multi-Tenant)是SaaS中的一个重要概念,指的是一种软件架构技术。在多个租户的环境下,共享同一套系统实例,这种技术也确保了租户之间的数据具有隔离性。也就是说,每个租户只能访问自己的数据,不能访问其他租户的数据。

基于不同的隔离级别,多租户技术通常有以下三种实现方案:

每个租户使用独立的数据库。这种方法的隔离级别较高,性能也比较好,但是成本较高。

租户之间共享数据库,但使用独立的Schema。这种方法的隔离级别较高,成本相对较低。

租户之间共享Schema,在表上添加租户字段。这种方法的隔离级别较低,但是数据共享程度最高。

数据库设计

Mybatis-plus在第3层隔离级别上,提供了基于分页插件的多租户的解决方案,我们对此来进行介绍。在正式开始前,首先做好准备工作创建两张表,在基础字段后都添加租户字段tenant_id:

引入依赖

在项目中导入需要的依赖:

实现

Mybatis-plus 配置类:

 

 

这里主要实现的功能:

  • 创建SQL解析器集合

  • 创建租户SQL解析器

  • 设置租户处理器,具体处理租户逻辑

这里暂时把租户的id固定写成3,来进行测试。测试执行全表语句:

 

使用插件解析执行的SQL语句,可以看到自动在查询条件后加上了租户过滤条件: 

那么在实际的项目中,怎么将租户信息传给租户处理器呢,根据情况我们可以从缓存或者请求头中获取,以从Request请求头获取为例: 

前端在发起http请求时,在Header中加入tenantId字段,后端在处理器中获取后,设置为当前这次请求的租户过滤条件。

如果是基于请求头携带租户信息的情况,那么在使用中可能会遇到一个坑,如果当使用多线程的时候,新开启的异步线程并不会自动携带当前线程的Request请求。

执行上面的方法,可以看出是获取不到当前的Request请求的,因此无法获得租户id,会导致后续报错空指针异常:

 

 

 

 修改的话也非常简单,开启RequestAttributes的子线程共享,修改上面的代码:

这样修改后,在异步线程中也能正常的获取租户信息了。

那么,有的小伙伴可能要问了,在业务中并不是所有的查询都需要过滤租户条件啊,针对这种情况,有两种方式来进行处理。

1、如果整张表的所有SQL操作都不需要针对租户进行操作,那么就对表进行过滤,修改doTableFilter方法,添加表的名称:

 

这样,在dept表的所有查询都不进行过滤: 

2、如果有一些特定的SQL语句不想被执行租户过滤,可以通过@SqlParser注解的形式开启,注意注解只能加在Mapper接口的方法上: 

或在分页拦截器中指定需要过滤的方法: 

上面这两种方式实现的功能相同,但是如果需要过滤的SQL语句很多,那么第二种方式配置起来会比较麻烦,因此建议通过注解的方式进行过滤。

除此之外,还有一个比较容易踩的坑就是在复制Bean时,不要复制租户id字段,否则会导致SQL语句报错:

 

查看报错可以看出,本身Bean的租户字段不为空的情况下,SQL又自动添加一次租户查询条件,因此导致了报错: 

我们可以修改复制Bean语句,手动忽略租户id字段,这里使用的是hutool的BeanUtil工具类,可以添加忽略字段。 

在忽略了租户id的拷贝后,查询可以正常执行。

最后,再来看一下对联表查询的支持,首先看一下包含子查询的SQL:

查看执行结果,可以看见,在子查询的内部也自动添加的租户查询条件: 

再来看一下使用Join进行联表查询: 

同样,会在左右两张表上都添加租户的过滤条件: 

再看一下不使用Join的普通联表查询: 

 

查看执行结果,可以看见在这种情况下,只在FROM关键字后面的第一张表上添加了租户的过滤条件。此外,如果使用这种查询方式,需要额外注意,用户需要手动在SQL语句中添加租户过滤。这个步骤可能需要一些时间,因为用户需要了解数据库结构和查询语言。用户可能会需要查阅数据库文档、查询最佳实践、或者寻求技术支持。

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

永钊源码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值