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.
450 lines
25 KiB
450 lines
25 KiB
|
1 month ago
|
# 安全与权限控制
|
||
|
|
|
||
|
|
<cite>
|
||
|
|
**本文引用的文件**
|
||
|
|
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.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)
|
||
|
|
- [AuthLoginUser.java](file://crm-auth/src/main/java/com/crm/auth/security/AuthLoginUser.java)
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
||
|
|
- [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.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)
|
||
|
|
- [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
||
|
|
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
|
||
|
|
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
|
||
|
|
- [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java)
|
||
|
|
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
|
||
|
|
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
|
||
|
|
</cite>
|
||
|
|
|
||
|
|
## 目录
|
||
|
|
1. [简介](#简介)
|
||
|
|
2. [项目结构](#项目结构)
|
||
|
|
3. [核心组件](#核心组件)
|
||
|
|
4. [架构总览](#架构总览)
|
||
|
|
5. [详细组件分析](#详细组件分析)
|
||
|
|
6. [依赖关系分析](#依赖关系分析)
|
||
|
|
7. [性能考虑](#性能考虑)
|
||
|
|
8. [故障排查指南](#故障排查指南)
|
||
|
|
9. [结论](#结论)
|
||
|
|
10. [附录](#附录)
|
||
|
|
|
||
|
|
## 简介
|
||
|
|
本文件围绕 CRM 后端的安全与权限控制体系,系统性阐述数据权限注解 @DataScope、数据范围助手 DataScopeHelper、可见性上下文 DataVisibilityContext 的设计与使用;并说明登录用户信息 LoginUser、安全工具类 SecurityUtils 的功能。文档覆盖权限验证流程、数据隔离机制与安全最佳实践,帮助读者快速理解并正确使用该模块。
|
||
|
|
|
||
|
|
## 项目结构
|
||
|
|
安全与权限相关能力分布在两个模块:
|
||
|
|
- crm-base:提供通用安全基础能力(注解、上下文、工具类、实体基类等)
|
||
|
|
- crm-auth:提供认证授权实现(JWT 过滤器、令牌服务、权限配置、数据范围拦截器等)
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
graph TB
|
||
|
|
subgraph "crm-base"
|
||
|
|
A["注解: DataScope"]
|
||
|
|
B["上下文: DataVisibilityContext"]
|
||
|
|
C["助手: DataScopeHelper"]
|
||
|
|
D["用户: LoginUser"]
|
||
|
|
E["工具: SecurityUtils"]
|
||
|
|
F["实体基类: BaseEntity / OwnedEntity"]
|
||
|
|
G["SQL注入器: CrmSqlInjector"]
|
||
|
|
H["MyBatis Plus 配置: MybatisPlusConfig"]
|
||
|
|
end
|
||
|
|
subgraph "crm-auth"
|
||
|
|
I["认证过滤器: JwtAuthenticationFilter"]
|
||
|
|
J["令牌服务: TokenService"]
|
||
|
|
K["权限配置: PermissionConfig"]
|
||
|
|
L["数据范围拦截器: DataScopeInterceptor"]
|
||
|
|
M["数据范围表映射: DataScopeTables"]
|
||
|
|
N["枚举: DataScopeEnum"]
|
||
|
|
O["控制器: AuthController"]
|
||
|
|
P["服务接口: IAuthService"]
|
||
|
|
Q["登录用户扩展: AuthLoginUser"]
|
||
|
|
end
|
||
|
|
A --> C
|
||
|
|
B --> C
|
||
|
|
D --> E
|
||
|
|
E --> B
|
||
|
|
I --> J
|
||
|
|
J --> Q
|
||
|
|
K --> I
|
||
|
|
L --> C
|
||
|
|
L --> B
|
||
|
|
L --> M
|
||
|
|
L --> N
|
||
|
|
O --> P
|
||
|
|
P --> Q
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.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)
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
||
|
|
- [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.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)
|
||
|
|
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
|
||
|
|
- [IAuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
||
|
|
- [AuthLoginUser.java](file://crm-auth/src/main/java/com/crm/auth/security/AuthLoginUser.java)
|
||
|
|
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
|
||
|
|
- [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java)
|
||
|
|
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
|
||
|
|
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.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)
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
||
|
|
- [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.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)
|
||
|
|
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
|
||
|
|
- [IAuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
||
|
|
- [AuthLoginUser.java](file://crm-auth/src/main/java/com/crm/auth/security/AuthLoginUser.java)
|
||
|
|
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
|
||
|
|
- [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java)
|
||
|
|
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
|
||
|
|
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
|
||
|
|
|
||
|
|
## 核心组件
|
||
|
|
- 数据权限注解 @DataScope:用于在 Mapper/Service 层声明数据范围规则,驱动后续的数据过滤逻辑。
|
||
|
|
- 数据范围助手 DataScopeHelper:封装数据范围解析、条件拼装等能力,供业务代码或拦截器调用。
|
||
|
|
- 可见性上下文 DataVisibilityContext:线程级上下文,承载当前请求的可见范围、租户/部门/角色等信息,贯穿整个请求生命周期。
|
||
|
|
- 登录用户 LoginUser:抽象的用户主体模型,包含用户标识、组织归属、角色权限等关键信息。
|
||
|
|
- 安全工具类 SecurityUtils:提供获取当前登录用户、判断权限、构造查询条件等便捷方法。
|
||
|
|
- 认证与授权支撑:
|
||
|
|
- JwtAuthenticationFilter:解析 JWT 并建立安全上下文。
|
||
|
|
- TokenService:令牌签发、校验、刷新等。
|
||
|
|
- PermissionConfig:安全过滤链与跨域等配置。
|
||
|
|
- DataScopeInterceptor:在 SQL 执行前根据 @DataScope 和上下文动态注入 WHERE 条件。
|
||
|
|
- DataScopeTables:维护表名到数据范围字段的映射。
|
||
|
|
- DataScopeEnum:定义数据范围类型(如全部、本部门、本人等)。
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.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)
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
||
|
|
- [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.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)
|
||
|
|
|
||
|
|
## 架构总览
|
||
|
|
下图展示从 HTTP 请求进入,到认证、鉴权、数据范围注入的完整链路。
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
sequenceDiagram
|
||
|
|
participant Client as "客户端"
|
||
|
|
participant Filter as "JwtAuthenticationFilter"
|
||
|
|
participant Service as "IAuthService"
|
||
|
|
participant Token as "TokenService"
|
||
|
|
participant Context as "DataVisibilityContext"
|
||
|
|
participant Interceptor as "DataScopeInterceptor"
|
||
|
|
participant DB as "数据库"
|
||
|
|
Client->>Filter : "HTTP 请求(携带Token)"
|
||
|
|
Filter->>Token : "解析并校验Token"
|
||
|
|
Token-->>Filter : "返回用户信息(AuthLoginUser)"
|
||
|
|
Filter->>Context : "设置当前登录用户与可见范围"
|
||
|
|
Filter->>Service : "放行至业务服务"
|
||
|
|
Service->>Interceptor : "触发数据范围处理"
|
||
|
|
Interceptor->>Context : "读取可见范围与表映射"
|
||
|
|
Interceptor->>DB : "注入WHERE条件后执行SQL"
|
||
|
|
DB-->>Client : "返回受限结果集"
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.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)
|
||
|
|
- [IAuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
||
|
|
|
||
|
|
## 详细组件分析
|
||
|
|
|
||
|
|
### 数据权限注解 @DataScope
|
||
|
|
- 作用位置:通常标注在 Mapper 方法或 Service 方法上,声明该方法的数据范围策略。
|
||
|
|
- 关键语义:指定数据范围类型(如全部、本部门、本人)、关联字段(如 dept_id、owner_id)、是否强制等。
|
||
|
|
- 使用建议:
|
||
|
|
- 对涉及多租户/多部门的查询,务必标注 @DataScope,避免越权访问。
|
||
|
|
- 结合 OwnedEntity 的 owner_id 字段,可实现“仅本人”数据隔离。
|
||
|
|
- 对于导出/批量操作,谨慎开启“全部范围”,需二次确认权限。
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
|
||
|
|
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java)
|
||
|
|
- [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java)
|
||
|
|
|
||
|
|
### 数据范围助手 DataScopeHelper
|
||
|
|
- 职责:
|
||
|
|
- 解析 @DataScope 注解参数。
|
||
|
|
- 基于 DataVisibilityContext 中的用户与组织信息,生成对应的 WHERE 条件片段。
|
||
|
|
- 提供统一的条件拼装 API,便于在复杂查询中复用。
|
||
|
|
- 典型用法:
|
||
|
|
- 在 Service 层通过助手构建查询条件,或在自定义 SQL 中拼接范围条件。
|
||
|
|
- 与分页、排序组合时,确保范围条件优先于其他过滤条件。
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [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)
|
||
|
|
|
||
|
|
### 可见性上下文 DataVisibilityContext
|
||
|
|
- 职责:
|
||
|
|
- 以 ThreadLocal 形式存储当前请求的可见范围、用户信息、租户/部门/角色等。
|
||
|
|
- 提供 set/get/clear 等方法,保证请求结束后清理上下文,避免内存泄漏。
|
||
|
|
- 设计要点:
|
||
|
|
- 在认证通过后立即填充上下文。
|
||
|
|
- 在请求结束或异常分支必须清理上下文。
|
||
|
|
- 对并发场景,确保上下文隔离,避免跨请求污染。
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
|
||
|
|
### 登录用户 LoginUser 与 AuthLoginUser
|
||
|
|
- LoginUser:抽象用户主体,包含用户ID、用户名、所属部门、角色集合等。
|
||
|
|
- AuthLoginUser:具体实现,由 TokenService 解析 JWT 后填充,作为安全上下文的权威来源。
|
||
|
|
- 使用建议:
|
||
|
|
- 所有鉴权逻辑应基于 LoginUser 进行,而非直接解析 Token。
|
||
|
|
- 敏感操作前校验用户状态、过期时间、角色权限。
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
|
||
|
|
- [AuthLoginUser.java](file://crm-auth/src/main/java/com/crm/auth/security/AuthLoginUser.java)
|
||
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
||
|
|
|
||
|
|
### 安全工具类 SecurityUtils
|
||
|
|
- 功能:
|
||
|
|
- 获取当前登录用户(LoginUser)。
|
||
|
|
- 判断用户是否拥有某角色/菜单权限。
|
||
|
|
- 辅助构造数据范围条件(可委托 DataScopeHelper)。
|
||
|
|
- 使用建议:
|
||
|
|
- 在 Controller/Service 中优先使用 SecurityUtils 获取上下文,避免重复解析。
|
||
|
|
- 权限判断失败时应抛出明确的异常,便于全局异常处理。
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [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)
|
||
|
|
|
||
|
|
### 认证与授权流程
|
||
|
|
- 认证流程:
|
||
|
|
- JwtAuthenticationFilter 拦截请求,解析 Token。
|
||
|
|
- TokenService 校验 Token 有效性,加载用户信息为 AuthLoginUser。
|
||
|
|
- 将用户信息写入 DataVisibilityContext,完成认证。
|
||
|
|
- 授权流程:
|
||
|
|
- PermissionConfig 配置白名单、拦截路径、角色/菜单权限校验。
|
||
|
|
- 业务方法可通过 SecurityUtils 进行细粒度权限判断。
|
||
|
|
- 数据范围通过 @DataScope + DataScopeInterceptor 自动注入 WHERE 条件。
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
flowchart TD
|
||
|
|
Start(["请求进入"]) --> Parse["解析Token"]
|
||
|
|
Parse --> Valid{"Token有效?"}
|
||
|
|
Valid --> |否| Deny["拒绝访问(未认证)"]
|
||
|
|
Valid --> |是| LoadUser["加载用户信息"]
|
||
|
|
LoadUser --> SetCtx["设置可见性上下文"]
|
||
|
|
SetCtx --> CheckPerm{"权限校验"}
|
||
|
|
CheckPerm --> |否| Deny
|
||
|
|
CheckPerm --> |是| ScopeCheck["@DataScope 数据范围处理"]
|
||
|
|
ScopeCheck --> Exec["执行业务SQL"]
|
||
|
|
Exec --> End(["返回结果"])
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
||
|
|
- [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
||
|
|
- [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
|
||
|
|
### 数据隔离机制
|
||
|
|
- 表级隔离:
|
||
|
|
- DataScopeTables 维护表名到数据范围字段的映射(如 dept_id、owner_id)。
|
||
|
|
- DataScopeInterceptor 在执行 SQL 前,根据映射与上下文注入 WHERE 条件。
|
||
|
|
- 行级隔离:
|
||
|
|
- 通过 OwnedEntity 的 owner_id 字段,实现“仅本人”数据隔离。
|
||
|
|
- 结合 DataScopeEnum 的“本人”范围,自动限制查询结果。
|
||
|
|
- 多层隔离:
|
||
|
|
- 支持“全部/本部门/本部门及子部门/本人”等多层级范围。
|
||
|
|
- 当存在多个范围注解时,按优先级合并条件,避免冲突。
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
classDiagram
|
||
|
|
class DataScope {
|
||
|
|
+范围类型
|
||
|
|
+关联字段
|
||
|
|
+是否强制
|
||
|
|
}
|
||
|
|
class DataScopeHelper {
|
||
|
|
+解析注解()
|
||
|
|
+生成条件()
|
||
|
|
+合并条件()
|
||
|
|
}
|
||
|
|
class DataVisibilityContext {
|
||
|
|
+用户信息
|
||
|
|
+可见范围
|
||
|
|
+set()/get()/clear()
|
||
|
|
}
|
||
|
|
class DataScopeInterceptor {
|
||
|
|
+拦截SQL()
|
||
|
|
+注入WHERE()
|
||
|
|
}
|
||
|
|
class DataScopeTables {
|
||
|
|
+表名->字段映射
|
||
|
|
}
|
||
|
|
class DataScopeEnum {
|
||
|
|
+全部
|
||
|
|
+本部门
|
||
|
|
+本部门及子部门
|
||
|
|
+本人
|
||
|
|
}
|
||
|
|
DataScope --> DataScopeHelper : "被解析"
|
||
|
|
DataScopeHelper --> DataVisibilityContext : "读取上下文"
|
||
|
|
DataScopeInterceptor --> DataScopeHelper : "调用助手"
|
||
|
|
DataScopeInterceptor --> DataScopeTables : "查映射"
|
||
|
|
DataScopeInterceptor --> DataScopeEnum : "匹配范围"
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.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)
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.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)
|
||
|
|
|
||
|
|
### 与 MyBatis Plus 的集成
|
||
|
|
- CrmSqlInjector:扩展 MP 的 SQL 注入器,支持在特定条件下注入范围条件。
|
||
|
|
- MybatisPlusConfig:注册拦截器与注入器,确保数据范围生效。
|
||
|
|
- 使用建议:
|
||
|
|
- 在需要自动注入范围的 Mapper 方法上标注 @DataScope。
|
||
|
|
- 对复杂查询,优先使用 DataScopeHelper 手动拼装条件,保证可控性。
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
|
||
|
|
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
|
||
|
|
|
||
|
|
## 依赖关系分析
|
||
|
|
- 低耦合高内聚:
|
||
|
|
- DataScopeHelper 专注条件拼装,不依赖 Web 容器。
|
||
|
|
- DataVisibilityContext 以 ThreadLocal 管理上下文,避免全局状态污染。
|
||
|
|
- DataScopeInterceptor 仅负责 SQL 拦截与注入,不关心业务细节。
|
||
|
|
- 外部依赖:
|
||
|
|
- JWT 解析与校验由 TokenService 提供。
|
||
|
|
- 权限配置由 PermissionConfig 集中管理。
|
||
|
|
- 数据库访问通过 MyBatis Plus 与自定义注入器协作。
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
graph LR
|
||
|
|
AuthController["AuthController"] --> IAuthService["IAuthService"]
|
||
|
|
IAuthService --> TokenService["TokenService"]
|
||
|
|
TokenService --> AuthLoginUser["AuthLoginUser"]
|
||
|
|
AuthLoginUser --> DataVisibilityContext["DataVisibilityContext"]
|
||
|
|
DataVisibilityContext --> DataScopeHelper["DataScopeHelper"]
|
||
|
|
DataScopeHelper --> DataScope["DataScope"]
|
||
|
|
DataScopeHelper --> DataScopeEnum["DataScopeEnum"]
|
||
|
|
DataScopeInterceptor["DataScopeInterceptor"] --> DataScopeHelper
|
||
|
|
DataScopeInterceptor --> DataScopeTables["DataScopeTables"]
|
||
|
|
DataScopeInterceptor --> CrmSqlInjector["CrmSqlInjector"]
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
|
||
|
|
- [IAuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
||
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
||
|
|
- [AuthLoginUser.java](file://crm-auth/src/main/java/com/crm/auth/security/AuthLoginUser.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)
|
||
|
|
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
|
||
|
|
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.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)
|
||
|
|
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
|
||
|
|
- [IAuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
||
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
|
||
|
|
- [AuthLoginUser.java](file://crm-auth/src/main/java/com/crm/auth/security/AuthLoginUser.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)
|
||
|
|
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
|
||
|
|
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.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)
|
||
|
|
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
|
||
|
|
|
||
|
|
## 性能考虑
|
||
|
|
- 上下文开销:DataVisibilityContext 使用 ThreadLocal,应避免在长任务或异步线程中误用,必要时显式传递。
|
||
|
|
- SQL 注入成本:DataScopeInterceptor 在每次 SQL 执行前注入条件,尽量复用条件片段,减少字符串拼接开销。
|
||
|
|
- 缓存策略:对频繁查询的部门树、角色权限等,可在服务层引入缓存(如 Redis),降低数据库压力。
|
||
|
|
- 批量操作:导出/导入时谨慎使用“全部范围”,必要时拆分批次并记录审计日志。
|
||
|
|
|
||
|
|
[本节为通用指导,无需引用具体文件]
|
||
|
|
|
||
|
|
## 故障排查指南
|
||
|
|
- 常见问题
|
||
|
|
- 未登录或 Token 失效:检查 JwtAuthenticationFilter 与 TokenService 的校验逻辑。
|
||
|
|
- 数据越权:确认 @DataScope 是否正确标注,DataScopeTables 映射是否完整。
|
||
|
|
- 上下文未清理:确保请求结束或异常分支调用 clear(),避免内存泄漏。
|
||
|
|
- 权限不足:检查 PermissionConfig 的路径白名单与角色/菜单权限配置。
|
||
|
|
- 定位步骤
|
||
|
|
- 打印 DataVisibilityContext 中的用户信息与可见范围。
|
||
|
|
- 查看 DataScopeInterceptor 注入的 WHERE 条件是否符合预期。
|
||
|
|
- 核对 DataScopeEnum 的范围类型与业务需求是否一致。
|
||
|
|
- 检查 OwnedEntity 的 owner_id 是否与当前用户匹配。
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.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)
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java)
|
||
|
|
- [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java)
|
||
|
|
|
||
|
|
## 结论
|
||
|
|
本安全与权限控制体系通过注解驱动的 @DataScope、上下文隔离的 DataVisibilityContext、以及拦截器层面的 SQL 注入,实现了灵活且强约束的数据隔离与权限控制。配合 JWT 认证与 TokenService,形成从认证、鉴权到数据访问的全链路安全保障。遵循本文的最佳实践,可有效避免越权访问与数据泄露风险。
|
||
|
|
|
||
|
|
[本节为总结,无需引用具体文件]
|
||
|
|
|
||
|
|
## 附录
|
||
|
|
- 最佳实践清单
|
||
|
|
- 所有涉及多租户/多部门的查询必须标注 @DataScope。
|
||
|
|
- 使用 OwnedEntity 的 owner_id 实现“仅本人”隔离。
|
||
|
|
- 在认证通过后立即设置 DataVisibilityContext,并在请求结束时清理。
|
||
|
|
- 对敏感操作增加二次确认与审计日志。
|
||
|
|
- 定期审查 DataScopeTables 映射与权限配置,确保与业务演进同步。
|
||
|
|
|
||
|
|
[本节为补充信息,无需引用具体文件]
|