You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
451 lines
23 KiB
451 lines
23 KiB
|
1 month ago
|
# 数据所有权控制
|
||
|
|
|
||
|
|
<cite>
|
||
|
|
**本文引用的文件**
|
||
|
|
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.java)
|
||
|
|
- [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
|
||
|
|
- [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
|
||
|
|
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java)
|
||
|
|
- [AuthUser.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthUser.java)
|
||
|
|
- [SysDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java)
|
||
|
|
- [SysUserDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java)
|
||
|
|
- [AuthUserMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/AuthUserMapper.java)
|
||
|
|
- [SysDeptMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysDeptMapper.java)
|
||
|
|
- [SysUserDeptMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysUserDeptMapper.java)
|
||
|
|
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java)
|
||
|
|
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
|
||
|
|
- [DataScopeIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/DataScopeIntegrationTest.java)
|
||
|
|
- [TestOwnedData.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/TestOwnedData.java)
|
||
|
|
- [TestOwnedDataMapper.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/TestOwnedDataMapper.java)
|
||
|
|
</cite>
|
||
|
|
|
||
|
|
## 目录
|
||
|
|
1. [简介](#简介)
|
||
|
|
2. [项目结构](#项目结构)
|
||
|
|
3. [核心组件](#核心组件)
|
||
|
|
4. [架构总览](#架构总览)
|
||
|
|
5. [详细组件分析](#详细组件分析)
|
||
|
|
6. [依赖关系分析](#依赖关系分析)
|
||
|
|
7. [性能考虑](#性能考虑)
|
||
|
|
8. [故障排查指南](#故障排查指南)
|
||
|
|
9. [结论](#结论)
|
||
|
|
10. [附录](#附录)
|
||
|
|
|
||
|
|
## 简介
|
||
|
|
本文件面向数据所有权控制能力,系统性说明 DataOwnership 注解的使用方式与配置项、不同数据范围级别 DataScopeLevel 的定义与应用场景,并给出在 Service 层使用数据所有权注解的实践方法。文档还涵盖如何扩展新的数据范围级别、数据权限验证的拦截机制以及性能优化建议,帮助读者快速掌握并安全落地部门级、用户级和全局级的数据访问控制。
|
||
|
|
|
||
|
|
## 项目结构
|
||
|
|
本项目将数据所有权控制的核心定义放在基础模块 crm-base 中,具体实现与集成位于认证模块 crm-auth 中:
|
||
|
|
- 基础能力(注解、上下文、工具)集中在 crm-base 的安全包下
|
||
|
|
- 拦截器、表映射、枚举与实体模型集中在 crm-auth 的安全包与领域模型中
|
||
|
|
- 测试用例覆盖端到端的数据范围校验流程
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
graph TB
|
||
|
|
subgraph "基础模块 crm-base"
|
||
|
|
A["DataOwnership 注解"]
|
||
|
|
B["DataScopeLevel 枚举"]
|
||
|
|
C["DataScopeHelper 工具"]
|
||
|
|
D["DataVisibilityContext 上下文"]
|
||
|
|
E["LoginUser 登录主体"]
|
||
|
|
F["SecurityUtils 安全工具"]
|
||
|
|
G["BaseServiceImpl 基类服务"]
|
||
|
|
H["CrmSqlInjector SQL注入器"]
|
||
|
|
end
|
||
|
|
subgraph "认证模块 crm-auth"
|
||
|
|
I["DataScopeInterceptor 拦截器"]
|
||
|
|
J["DataScopeTables 表映射"]
|
||
|
|
K["DataScopeEnum 数据范围枚举"]
|
||
|
|
L["AuthUser 用户实体"]
|
||
|
|
M["SysDept 部门实体"]
|
||
|
|
N["SysUserDept 用户-部门关联"]
|
||
|
|
O["AuthUserMapper / SysDeptMapper / SysUserDeptMapper"]
|
||
|
|
end
|
||
|
|
A --> C
|
||
|
|
B --> C
|
||
|
|
C --> D
|
||
|
|
D --> I
|
||
|
|
I --> J
|
||
|
|
I --> O
|
||
|
|
I --> K
|
||
|
|
L --> O
|
||
|
|
M --> O
|
||
|
|
N --> O
|
||
|
|
G --> H
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.java)
|
||
|
|
- [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
|
||
|
|
- [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java)
|
||
|
|
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java)
|
||
|
|
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
|
||
|
|
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java)
|
||
|
|
- [AuthUser.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthUser.java)
|
||
|
|
- [SysDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java)
|
||
|
|
- [SysUserDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java)
|
||
|
|
- [AuthUserMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/AuthUserMapper.java)
|
||
|
|
- [SysDeptMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysDeptMapper.java)
|
||
|
|
- [SysUserDeptMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysUserDeptMapper.java)
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.java)
|
||
|
|
- [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
|
||
|
|
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java)
|
||
|
|
|
||
|
|
## 核心组件
|
||
|
|
- DataOwnership 注解:用于标注 Service 方法或类,声明该方法的数据所有权策略与范围级别
|
||
|
|
- DataScopeLevel:定义数据范围级别(如部门级、用户级、全局级等),决定查询时自动附加的过滤条件
|
||
|
|
- DataScopeHelper:提供计算当前可见数据范围的辅助方法,结合上下文与用户信息生成过滤条件
|
||
|
|
- DataVisibilityContext:线程局部上下文,承载当前请求的数据可见性范围、租户信息等
|
||
|
|
- LoginUser 与 SecurityUtils:封装当前登录用户信息与获取方式
|
||
|
|
- DataScopeInterceptor:拦截器,解析注解、读取上下文、组装 SQL 片段并注入到查询语句
|
||
|
|
- DataScopeTables:维护表名与字段名的映射,确保 SQL 片段正确注入
|
||
|
|
- BaseServiceImpl 与 CrmSqlInjector:在 MyBatis-Plus 层面统一注入数据范围条件
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.java)
|
||
|
|
- [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
|
||
|
|
- [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
|
||
|
|
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java)
|
||
|
|
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
|
||
|
|
|
||
|
|
## 架构总览
|
||
|
|
数据所有权控制的执行链路如下:
|
||
|
|
- 调用方进入 Service 方法前,由 DataScopeInterceptor 解析 DataOwnership 注解
|
||
|
|
- 根据 DataScopeLevel 与当前 LoginUser 的信息,通过 DataScopeHelper 计算可见范围
|
||
|
|
- 将范围条件注入到 SQL 中(通过 CrmSqlInjector 与 DataScopeTables 映射)
|
||
|
|
- 查询返回结果即已按数据范围过滤
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
sequenceDiagram
|
||
|
|
participant Client as "客户端"
|
||
|
|
participant Interceptor as "DataScopeInterceptor"
|
||
|
|
participant Context as "DataVisibilityContext"
|
||
|
|
participant Helper as "DataScopeHelper"
|
||
|
|
participant Mapper as "MyBatis Mapper"
|
||
|
|
participant DB as "数据库"
|
||
|
|
Client->>Interceptor : "进入受保护的方法"
|
||
|
|
Interceptor->>Interceptor : "解析 DataOwnership 注解"
|
||
|
|
Interceptor->>Context : "设置/读取可见范围上下文"
|
||
|
|
Interceptor->>Helper : "计算数据范围条件"
|
||
|
|
Helper-->>Interceptor : "返回过滤条件"
|
||
|
|
Interceptor->>Mapper : "注入 SQL 片段"
|
||
|
|
Mapper->>DB : "执行带条件的查询"
|
||
|
|
DB-->>Client : "返回已过滤的结果集"
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
|
||
|
|
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
|
||
|
|
|
||
|
|
## 详细组件分析
|
||
|
|
|
||
|
|
### DataOwnership 注解与 DataScopeLevel 级别
|
||
|
|
- DataOwnership 注解用于声明方法或类的数据所有权策略,包括范围级别、是否强制校验、是否忽略某些表等
|
||
|
|
- DataScopeLevel 定义不同数据范围级别,常见包括:
|
||
|
|
- 部门级:仅可见本部门及子部门数据
|
||
|
|
- 用户级:仅可见本人数据
|
||
|
|
- 全局级:可见全部数据(通常用于管理员)
|
||
|
|
- 注解可配合自定义规则,例如指定特定字段作为归属标识(如 owner_id、dept_id)
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.java)
|
||
|
|
- [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java)
|
||
|
|
|
||
|
|
#### 类图(注解与级别)
|
||
|
|
```mermaid
|
||
|
|
classDiagram
|
||
|
|
class DataOwnership {
|
||
|
|
+scopeLevel()
|
||
|
|
+forceCheck()
|
||
|
|
+ignoreTables()
|
||
|
|
+ownerField()
|
||
|
|
}
|
||
|
|
class DataScopeLevel {
|
||
|
|
<<enumeration>>
|
||
|
|
+DEPT
|
||
|
|
+USER
|
||
|
|
+GLOBAL
|
||
|
|
}
|
||
|
|
DataOwnership --> DataScopeLevel : "引用"
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.java)
|
||
|
|
- [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java)
|
||
|
|
|
||
|
|
### 上下文与工具:DataVisibilityContext、DataScopeHelper、LoginUser、SecurityUtils
|
||
|
|
- DataVisibilityContext:保存当前请求的数据可见范围、租户 ID、操作人等上下文信息
|
||
|
|
- DataScopeHelper:根据上下文与用户信息计算数据范围条件(如 dept_id IN (...) 或 owner_id = ?)
|
||
|
|
- LoginUser:封装当前登录用户的基本信息(用户ID、部门ID、角色等)
|
||
|
|
- SecurityUtils:提供从安全上下文中获取 LoginUser 的工具方法
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
|
||
|
|
- [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java)
|
||
|
|
|
||
|
|
#### 类图(上下文与工具)
|
||
|
|
```mermaid
|
||
|
|
classDiagram
|
||
|
|
class DataVisibilityContext {
|
||
|
|
+setScope(scope)
|
||
|
|
+getScope()
|
||
|
|
+setTenantId(id)
|
||
|
|
+getTenantId()
|
||
|
|
}
|
||
|
|
class DataScopeHelper {
|
||
|
|
+computeScopeCondition(level, user)
|
||
|
|
+buildDeptFilter(deptIds)
|
||
|
|
+buildOwnerFilter(ownerId)
|
||
|
|
}
|
||
|
|
class LoginUser {
|
||
|
|
+userId
|
||
|
|
+deptId
|
||
|
|
+roles
|
||
|
|
}
|
||
|
|
class SecurityUtils {
|
||
|
|
+getCurrentUser()
|
||
|
|
}
|
||
|
|
DataScopeHelper --> DataVisibilityContext : "读写上下文"
|
||
|
|
DataScopeHelper --> LoginUser : "读取用户信息"
|
||
|
|
SecurityUtils --> LoginUser : "获取当前用户"
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
|
||
|
|
- [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java)
|
||
|
|
|
||
|
|
### 拦截器与表映射:DataScopeInterceptor、DataScopeTables
|
||
|
|
- DataScopeInterceptor:在方法执行前解析 DataOwnership 注解,依据 DataScopeLevel 与用户信息计算过滤条件,并将条件注入到 SQL
|
||
|
|
- DataScopeTables:维护表名与字段映射,确保 SQL 片段注入到正确的表与字段上
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
|
||
|
|
|
||
|
|
#### 序列图(拦截流程)
|
||
|
|
```mermaid
|
||
|
|
sequenceDiagram
|
||
|
|
participant Svc as "Service方法"
|
||
|
|
participant Int as "DataScopeInterceptor"
|
||
|
|
participant Tbl as "DataScopeTables"
|
||
|
|
participant Sql as "SQL注入器"
|
||
|
|
Svc->>Int : "进入受保护方法"
|
||
|
|
Int->>Int : "解析 DataOwnership"
|
||
|
|
Int->>Tbl : "查找表字段映射"
|
||
|
|
Int->>Sql : "注入 WHERE 条件"
|
||
|
|
Sql-->>Svc : "返回带条件的查询"
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
|
||
|
|
|
||
|
|
### 数据范围枚举与实体模型:DataScopeEnum、AuthUser、SysDept、SysUserDept
|
||
|
|
- DataScopeEnum:定义系统内数据范围枚举值,与 DataScopeLevel 协同使用
|
||
|
|
- AuthUser:用户实体,包含用户基本信息与所属部门
|
||
|
|
- SysDept:部门实体,支持层级结构
|
||
|
|
- SysUserDept:用户与部门的关联表,用于多部门归属
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java)
|
||
|
|
- [AuthUser.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthUser.java)
|
||
|
|
- [SysDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java)
|
||
|
|
- [SysUserDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java)
|
||
|
|
|
||
|
|
#### 类图(实体与枚举)
|
||
|
|
```mermaid
|
||
|
|
classDiagram
|
||
|
|
class DataScopeEnum {
|
||
|
|
<<enumeration>>
|
||
|
|
+DEPT
|
||
|
|
+USER
|
||
|
|
+GLOBAL
|
||
|
|
}
|
||
|
|
class AuthUser {
|
||
|
|
+id
|
||
|
|
+name
|
||
|
|
+deptId
|
||
|
|
}
|
||
|
|
class SysDept {
|
||
|
|
+id
|
||
|
|
+parentId
|
||
|
|
+name
|
||
|
|
}
|
||
|
|
class SysUserDept {
|
||
|
|
+userId
|
||
|
|
+deptId
|
||
|
|
}
|
||
|
|
AuthUser --> SysDept : "属于"
|
||
|
|
AuthUser --> SysUserDept : "关联"
|
||
|
|
SysDept --> SysUserDept : "被关联"
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java)
|
||
|
|
- [AuthUser.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthUser.java)
|
||
|
|
- [SysDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java)
|
||
|
|
- [SysUserDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java)
|
||
|
|
|
||
|
|
### Service 层使用示例与扩展新级别
|
||
|
|
- 在 Service 方法上使用 DataOwnership 注解,指定 DataScopeLevel 与必要参数(如 ownerField)
|
||
|
|
- 若需新增数据范围级别,可在 DataScopeLevel 中添加枚举值,并在 DataScopeHelper 中补充对应计算逻辑
|
||
|
|
- 建议在 BaseServiceImpl 中统一处理通用数据范围注入,减少重复代码
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java)
|
||
|
|
- [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
|
||
|
|
#### 流程图(扩展新级别)
|
||
|
|
```mermaid
|
||
|
|
flowchart TD
|
||
|
|
Start(["开始"]) --> AddEnum["在 DataScopeLevel 添加新级别"]
|
||
|
|
AddEnum --> UpdateHelper["在 DataScopeHelper 实现新级别的计算逻辑"]
|
||
|
|
UpdateHelper --> UpdateTables["在 DataScopeTables 配置新级别对应的表字段映射"]
|
||
|
|
UpdateTables --> Test["编写单元测试验证"]
|
||
|
|
Test --> End(["完成"])
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
|
||
|
|
|
||
|
|
### 数据权限验证的拦截机制
|
||
|
|
- DataScopeInterceptor 负责解析注解、读取上下文、计算范围条件并注入 SQL
|
||
|
|
- 若未检测到有效登录用户或范围级别不合法,应抛出权限异常
|
||
|
|
- 可通过 CrmSqlInjector 统一注入 WHERE 条件,保证所有查询均受控
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
|
||
|
|
|
||
|
|
#### 序列图(权限验证)
|
||
|
|
```mermaid
|
||
|
|
sequenceDiagram
|
||
|
|
participant Req as "请求"
|
||
|
|
participant Int as "DataScopeInterceptor"
|
||
|
|
participant Sec as "SecurityUtils"
|
||
|
|
participant Hlp as "DataScopeHelper"
|
||
|
|
participant Inj as "CrmSqlInjector"
|
||
|
|
Req->>Int : "进入方法"
|
||
|
|
Int->>Sec : "获取当前用户"
|
||
|
|
Sec-->>Int : "返回 LoginUser"
|
||
|
|
Int->>Hlp : "计算数据范围"
|
||
|
|
Hlp-->>Int : "返回过滤条件"
|
||
|
|
Int->>Inj : "注入 SQL 条件"
|
||
|
|
Inj-->>Req : "执行受控查询"
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
|
||
|
|
|
||
|
|
## 依赖关系分析
|
||
|
|
- DataOwnership 注解依赖 DataScopeLevel 枚举
|
||
|
|
- DataScopeHelper 依赖 DataVisibilityContext、LoginUser 与安全工具
|
||
|
|
- DataScopeInterceptor 依赖 DataScopeTables、DataScopeHelper 与 SQL 注入器
|
||
|
|
- BaseServiceImpl 与 CrmSqlInjector 共同完成 MyBatis-Plus 层面的条件注入
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
graph LR
|
||
|
|
A["DataOwnership"] --> B["DataScopeLevel"]
|
||
|
|
C["DataScopeHelper"] --> D["DataVisibilityContext"]
|
||
|
|
C --> E["LoginUser"]
|
||
|
|
F["DataScopeInterceptor"] --> G["DataScopeTables"]
|
||
|
|
F --> C
|
||
|
|
F --> H["CrmSqlInjector"]
|
||
|
|
I["BaseServiceImpl"] --> H
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.java)
|
||
|
|
- [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
|
||
|
|
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java)
|
||
|
|
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.java)
|
||
|
|
- [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
|
||
|
|
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java)
|
||
|
|
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
|
||
|
|
|
||
|
|
## 性能考虑
|
||
|
|
- 避免在每次请求中重复计算用户部门树:对部门层级进行缓存,减少递归查询
|
||
|
|
- 合理设计 DataScopeTables 映射,避免不必要的表扫描;为常用过滤字段建立索引
|
||
|
|
- 在 DataScopeHelper 中尽量使用集合批量查询,减少多次 IO
|
||
|
|
- 对于大数据量查询,优先在数据库侧进行过滤,避免将大量数据拉取到内存再过滤
|
||
|
|
- 使用分页查询并结合数据范围条件,降低单次查询压力
|
||
|
|
|
||
|
|
[本节为通用指导,无需具体文件来源]
|
||
|
|
|
||
|
|
## 故障排查指南
|
||
|
|
- 常见问题:
|
||
|
|
- 未正确配置 DataScopeTables 导致 SQL 注入失败
|
||
|
|
- 当前用户为空或权限不足导致范围计算异常
|
||
|
|
- 数据范围级别与业务字段不匹配导致查询结果为空
|
||
|
|
- 排查步骤:
|
||
|
|
- 检查 DataOwnership 注解的参数是否正确
|
||
|
|
- 确认 DataScopeLevel 与业务字段一致
|
||
|
|
- 查看 DataScopeHelper 计算的过滤条件是否符合预期
|
||
|
|
- 检查数据库索引与 SQL 执行计划
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
|
||
|
|
## 结论
|
||
|
|
数据所有权控制通过注解驱动与拦截器机制,实现了灵活且可扩展的数据范围管理。借助 DataOwnership 与 DataScopeLevel,开发者可以便捷地在 Service 层声明数据访问策略,并通过统一的拦截与注入机制保障数据安全。建议在生产环境中结合缓存、索引与分页等手段优化性能,同时完善测试覆盖以确保行为稳定。
|
||
|
|
|
||
|
|
[本节为总结性内容,无需具体文件来源]
|
||
|
|
|
||
|
|
## 附录
|
||
|
|
- 端到端测试参考:
|
||
|
|
- 数据范围集成测试:[DataScopeIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/DataScopeIntegrationTest.java)
|
||
|
|
- 测试实体与映射:[TestOwnedData.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/TestOwnedData.java)、[TestOwnedDataMapper.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/TestOwnedDataMapper.java)
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataScopeIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/DataScopeIntegrationTest.java)
|
||
|
|
- [TestOwnedData.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/TestOwnedData.java)
|
||
|
|
- [TestOwnedDataMapper.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/TestOwnedDataMapper.java)
|