权限控制
功能描述
权限控制由 资源权限 与 数据权限 两部分组成,共同构建完整的权限控制体系。
资源权限
由 blade-auth-spring-boot-starter 提供核心支持,主要功能包括:
- 权限信息的加载与初始化
- 接口级别的访问控制
- 基于角色、权限码的权限验证
数据权限
由 ORM 组件提供支持:
blade-data-mybatis-plus-spring-boot-starter:MyBatis-Plus 数据权限实现blade-jimmer-spring-boot-starter:Jimmer 框架数据权限实现
主要功能:
- 动态 SQL 注入
- 行级数据过滤
更新记录
v3.1.0
初次实现
GAV 坐标
<!-- 必要组件 -->
<dependency>
<groupId>team.aikero.blade</groupId>
<artifactId>blade-auth-spring-boot-starter</artifactId>
</dependency>
<!-- 可选:ORM 组件 -->
<dependency>
<groupId>team.aikero.blade</groupId>
<artifactId>blade-data-mybatis-plus-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>team.aikero.blade</groupId>
<artifactId>blade-jimmer-spring-boot-starter</artifactId>
</dependency># 必要组件
implementation(commonLibs.blade.auth.spring.boot.starter)
# 可选:ORM 组件
implementation(commonLibs.blade.data.mybatis.plus.spring.boot.starter)
implementation(commonLibs.blade.jimmer.spring.boot.starter)快速集成
选择合适的 GAV,在项目中的 pom.xml 添加依赖。
implementation(commonLibs.blade.auth.spring.boot.starter) implementation(commonLibs.blade.jimmer.spring.boot.starter)在项目的
application.yaml中添加下方代码。spring: config: import: - optional:nacos:blade-config <--- 在项目配置之前引入此配置 - optional:nacos:${spring.application.name}
详细说明
配置示例
默认情况下,blade-config 提供全局公共配置
若有特殊定制需求可以在application.yml文件中,可以进行以下配置:
blade:
mybatis-plus:
permission:
# 是否开启数据权限,默认为 false
enabled: true集成步骤
接口标注
@PreCheckPermission预校验注解// 权限编码全局唯一,建议按照 `服务名.模块名.功能名` 进行编码,例如:`auth.permission.dataAllocation`。 @PreCheckPermission(name = "[auth_1.0.0]权限示例", value = "exmple.test.post") @PostMapping("/post") public String post() { return "Hello, World!"; }应用启动时自动上报至 UACS/系统管理/权限码管理
需指定可访问的客户端,否则任何来源均不可访问该接口
通过UACS/系统管理/角色管理授权接口

代码示例
mybatis 数据权限使用示例
提示
- 若数据权限字段缺失,将无法生效。默认跳过缺失字段的 sql 条件拼接。
- 支持联表、with 语句、表别名等复杂语句
- 当数据权限开启时,若更新或删除 受影响行数为 0 条,将抛出
NotPermissionException异常。
启用数据权限拦截器
blade: mybatis-plus: permission: enabled: true创建一个实体类,继承 BaseEntityWithOrg(包含创建人 Id 及 组织 Id 字段)。
@TableName("`order`") class Order : BaseEntityWithOrg() { var id: Long? = null var name: String? = null }Controller 标注
@PreCheckPermission权限注解@RestController @RequestMapping("/order") class OrderController(private val orderService: OrderService) { @PostMapping @PreCheckPermission(name = "[example_3.1.0]权限示例", value = "example.order.select") fun selectAll():List<Order> { return orderService.selectList() } }按集成步骤配置接口关系,配置权限码,并指定客户端。
分配角色权限数据范围后,框架会根据用户的角色及权限,自动计算出数据权限范围,并注入到上下文中。例如:
// orderService.selectList() SELECT id, name, reviser_id, revised_time, organization_id, deleted, creator_id, created_time FROM `order` WHERE (creator_id = '1' OR organization_id IN ('1', '3'))
jimmer 数据权限使用示例
提示
- jimmer 强类型控制,实现指定接口,视为开启数据权限过滤拼接
- jimmer 中 SqlClient 相关 API 受权限过滤器控制;而 Repository 仅查询方法支持,更新、删除动作涉及数据权限需通过 sqlClient 进行操作。
- 当数据权限开启时,若更新或删除受影响行数为 0 条,需手动判断并给予提示。
创建一个实体类,实现
OrgWithFilter或CreatorWithFilter接口。@Entity @Table(name = "`order`") interface Order : LongId, CreatedTime, RevisedTime, Reviser, OrgWithFilter { /** * 订单名称 */ val name: String }Controller 标注
@PreCheckPermission权限注解@RestController @RequestMapping("/order") class OrderController(private val orderRepository: OrderRepository) { @PostMapping @PreCheckPermission(name = "[example_3.1.0]权限示例", value = "example.order.select") fun selectAll():List<Order> { return orderRepository.selectList() } }按集成步骤配置接口关系,配置权限码,并指定客户端。
分配角色权限数据范围后,框架会根据用户的角色及权限,自动计算出数据权限范围,并注入到上下文中。例如:
select tb_1_.ID, tb_1_.CREATED_TIME, tb_1_.REVISED_TIME, tb_1_.REVISER_ID, tb_1_.REVISER_NAME, tb_1_.CREATOR_ID, tb_1_.CREATOR_NAME, tb_1_.ORGANIZATION_ID, tb_1_.NAME from `order` tb_1_ where tb_1_.CREATOR_ID = '1' or tb_1_.ORGANIZATION_ID IN ('1','3')
数据权限 API
数据权限允许通过 API 进行控制、计算数据权限范围用于手动处理。
注意
权限信息存储于 CurrentUser,多线程场景下需注意深拷贝,或使用 TransmittableThreadLocal
// 获取当前上下文匹配的权限编码
DataPermissions.currentPermissionCodes()
// 启用指定编码的数据权限,此操作会覆盖当前上下文数据权限
DataPermissions.enable(vararg codes: String)
// 关闭当前数据权限
DataPermissions.disable()
// 计算当前权限的数据范围,按范围分组,返回 Map<DataScope,List>
DataPermissions.autoCompute()
// 计算当前权限的数据范围,按指定字段聚合,返回 List
DataPermissions.autoComputeByColumn(column: String)