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.
 
 
 
 
 
 

33 KiB

安全框架

**本文引用的文件** - [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.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) - [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) - [AuthLoginUser.java](file://crm-auth/src/main/java/com/crm/auth/security/AuthLoginUser.java) - [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.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) - [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) - [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java) - [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java) - [SysRoleMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysRoleMapper.java) - [SysMenuMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysMenuMapper.java) - [SysDeptMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysDeptMapper.java) - [SysUserRoleMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysUserRoleMapper.java) - [SysUserDeptMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysUserDeptMapper.java) - [DataScopeIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/DataScopeIntegrationTest.java)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考量
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件为安全框架的全面技术文档,聚焦数据所有权注解 DataOwnership 的使用、数据范围级别 DataScopeLevel 的配置与数据可见性上下文 DataVisibilityContext 的管理;说明 LoginUser 用户信息模型与 SecurityUtils 工具类的常用方法;解释数据权限控制的实现原理(拦截器机制、SQL 过滤、用户权限验证);并提供安全配置最佳实践与自定义权限控制扩展指导。

项目结构

安全能力主要分布在两个模块:

  • crm-base:提供通用安全基础能力,包括数据所有权注解、数据范围级别枚举、数据可见性上下文、登录用户模型、安全工具类以及 MyBatis-Plus SQL 注入器。
  • crm-auth:提供认证授权与安全配置,包括 JWT 过滤器、令牌服务、数据范围拦截器、表映射配置、权限配置与认证服务实现。
graph TB
subgraph "crm-base"
A["DataOwnership<br/>注解"]
B["DataScopeLevel<br/>数据范围级别"]
C["DataVisibilityContext<br/>数据可见性上下文"]
D["LoginUser<br/>用户信息模型"]
E["SecurityUtils<br/>安全工具类"]
F["DataScopeHelper<br/>数据范围辅助"]
G["CrmSqlInjector<br/>SQL注入器"]
H["MybatisPlusConfig<br/>MP配置"]
end
subgraph "crm-auth"
I["JwtAuthenticationFilter<br/>JWT过滤器"]
J["TokenService<br/>令牌服务"]
K["DataScopeInterceptor<br/>数据范围拦截器"]
L["DataScopeTables<br/>数据范围表映射"]
M["PermissionConfig<br/>权限配置"]
N["SecurityConfig<br/>安全配置"]
O["AuthLoginUser<br/>认证用户"]
P["AuthService / Impl<br/>认证服务"]
Q["Sys*Mapper<br/>系统表映射"]
end
A --> F
B --> F
C --> F
D --> E
E --> C
F --> G
G --> H
I --> J
I --> O
K --> L
K --> C
M --> N
P --> Q

图表来源

  • DataOwnership.java:1-200
  • DataScopeLevel.java:1-200
  • DataVisibilityContext.java:1-200
  • LoginUser.java:1-200
  • SecurityUtils.java:1-200
  • DataScopeHelper.java:1-200
  • CrmSqlInjector.java:1-200
  • MybatisPlusConfig.java:1-200
  • JwtAuthenticationFilter.java:1-200
  • TokenService.java:1-200
  • DataScopeInterceptor.java:1-200
  • DataScopeTables.java:1-200
  • PermissionConfig.java:1-200
  • SecurityConfig.java:1-200
  • AuthLoginUser.java:1-200
  • AuthService.java:1-200
  • AuthServiceImpl.java:1-200
  • SysRoleMapper.java:1-200
  • SysMenuMapper.java:1-200
  • SysDeptMapper.java:1-200
  • SysUserRoleMapper.java:1-200
  • SysUserDeptMapper.java:1-200

章节来源

  • DataOwnership.java:1-200
  • DataScopeLevel.java:1-200
  • DataVisibilityContext.java:1-200
  • LoginUser.java:1-200
  • SecurityUtils.java:1-200
  • DataScopeInterceptor.java:1-200
  • DataScopeTables.java:1-200
  • JwtAuthenticationFilter.java:1-200
  • TokenService.java:1-200
  • PermissionConfig.java:1-200
  • SecurityConfig.java:1-200
  • DataScope.java:1-200
  • DataScopeHelper.java:1-200
  • CrmSqlInjector.java:1-200
  • MybatisPlusConfig.java:1-200
  • AuthService.java:1-200
  • AuthServiceImpl.java:1-200
  • SysRoleMapper.java:1-200
  • SysMenuMapper.java:1-200
  • SysDeptMapper.java:1-200
  • SysUserRoleMapper.java:1-200
  • SysUserDeptMapper.java:1-200

核心组件

  • 数据所有权注解 DataOwnership:用于声明实体或查询的数据所有权策略,结合数据范围级别进行细粒度控制。
  • 数据范围级别 DataScopeLevel:定义数据可见性的层级(如本人、本部门、本部门及子部门、全公司、自定义等),配合注解驱动权限过滤。
  • 数据可见性上下文 DataVisibilityContext:线程级上下文,保存当前请求的可见范围、租户、组织等信息,贯穿整个请求生命周期。
  • 登录用户模型 LoginUser:封装当前登录用户的身份、角色、部门、权限集合等关键信息,供业务层与工具类使用。
  • 安全工具类 SecurityUtils:提供获取当前用户、校验权限、解析上下文等便捷方法,简化业务代码中的安全调用。
  • 数据范围辅助 DataScopeHelper:聚合数据范围计算逻辑,基于上下文与注解生成过滤条件。
  • SQL 注入器 CrmSqlInjector:在 MyBatis-Plus 执行前自动拼接数据范围过滤 SQL,实现无侵入式数据权限控制。
  • 数据范围拦截器 DataScopeInterceptor:在请求进入 Service/Mapper 层时,根据注解与上下文设置数据可见范围。
  • JWT 过滤器 JwtAuthenticationFilter:从请求头解析 Token,完成认证并填充 Security 上下文。
  • 令牌服务 TokenService:负责 Token 的签发、校验、刷新与过期处理。
  • 权限配置 PermissionConfig 与安全配置 SecurityConfig:统一注册过滤器、拦截器、跨域、接口鉴权规则等。

章节来源

  • DataOwnership.java:1-200
  • DataScopeLevel.java:1-200
  • DataVisibilityContext.java:1-200
  • LoginUser.java:1-200
  • SecurityUtils.java:1-200
  • DataScopeHelper.java:1-200
  • CrmSqlInjector.java:1-200
  • DataScopeInterceptor.java:1-200
  • JwtAuthenticationFilter.java:1-200
  • TokenService.java:1-200
  • PermissionConfig.java:1-200
  • SecurityConfig.java:1-200

架构总览

整体流程分为三层:

  • 接入层:JwtAuthenticationFilter 解析 Token,建立认证上下文;SecurityConfig 统一装配安全相关 Bean。
  • 控制层:DataScopeInterceptor 根据注解与上下文设置数据可见范围;PermissionConfig 管理接口级权限策略。
  • 数据层:CrmSqlInjector 在 SQL 执行前注入数据范围过滤条件;DataScopeHelper 计算具体过滤表达式;Sys*Mapper 读取用户角色、部门等权限数据。
sequenceDiagram
participant Client as "客户端"
participant Filter as "JwtAuthenticationFilter"
participant Token as "TokenService"
participant Interceptor as "DataScopeInterceptor"
participant Context as "DataVisibilityContext"
participant MP as "MyBatis-Plus"
participant Injector as "CrmSqlInjector"
participant Mapper as "Sys*Mapper"
Client->>Filter : "HTTP 请求(携带Token)"
Filter->>Token : "校验Token/解析用户"
Token-->>Filter : "返回用户信息"
Filter-->>Client : "通过认证"
Client->>Interceptor : "进入业务方法"
Interceptor->>Context : "设置数据可见范围"
Interceptor-->>Client : "继续执行业务"
MP->>Injector : "执行SQL前拦截"
Injector->>Context : "读取可见范围"
Injector->>Mapper : "注入过滤条件后执行"
Mapper-->>MP : "返回结果集"

图表来源

  • JwtAuthenticationFilter.java:1-200
  • TokenService.java:1-200
  • DataScopeInterceptor.java:1-200
  • DataVisibilityContext.java:1-200
  • CrmSqlInjector.java:1-200
  • SysRoleMapper.java:1-200
  • SysDeptMapper.java:1-200
  • SysUserRoleMapper.java:1-200
  • SysUserDeptMapper.java:1-200

详细组件分析

数据所有权注解 DataOwnership 与数据范围级别 DataScopeLevel

  • DataOwnership 用于标注实体或查询方法,声明数据归属策略(如“仅本人”、“本部门”、“本部门及子部门”、“全公司”、“自定义”)。
  • DataScopeLevel 枚举定义了不同数据可见性层级,通常与 DataOwnership 配合使用,决定最终生成的 SQL 过滤条件。
  • 典型用法:在 Service 方法上添加注解,指定数据范围级别;或在实体类上声明默认的数据所有权策略。
classDiagram
class DataOwnership {
+value() String
+scope() DataScopeLevel
+excludeFields() String[]
}
class DataScopeLevel {
<<enumeration>>
+ALL
+DEPT_AND_CHILD
+DEPT_ONLY
+SELF
+CUSTOM
}
DataOwnership --> DataScopeLevel : "引用"

图表来源

  • DataOwnership.java:1-200
  • DataScopeLevel.java:1-200

章节来源

  • DataOwnership.java:1-200
  • DataScopeLevel.java:1-200

数据可见性上下文 DataVisibilityContext 管理

  • DataVisibilityContext 以 ThreadLocal 形式存储当前请求的数据可见范围、租户、组织、用户标识等。
  • 生命周期:请求开始时由拦截器初始化,业务方法中可通过工具类读取或更新,请求结束时清理。
  • 常见操作:设置可见范围、获取当前用户、合并多来源权限、清空上下文避免内存泄漏。
flowchart TD
Start(["请求开始"]) --> InitCtx["初始化上下文"]
InitCtx --> SetScope["设置数据可见范围"]
SetScope --> Business["执行业务逻辑"]
Business --> ReadCtx["读取上下文参数"]
ReadCtx --> UpdateCtx{"需要更新上下文?"}
UpdateCtx --> |是| MergePerms["合并权限/范围"]
UpdateCtx --> |否| Continue["继续执行"]
MergePerms --> Continue
Continue --> Cleanup["请求结束清理上下文"]
Cleanup --> End(["请求结束"])

图表来源

  • DataVisibilityContext.java:1-200
  • DataScopeInterceptor.java:1-200

章节来源

  • DataVisibilityContext.java:1-200
  • DataScopeInterceptor.java:1-200

LoginUser 用户信息模型与 SecurityUtils 工具类

  • LoginUser 包含用户 ID、用户名、角色列表、部门信息、权限集合等,作为认证后的主体对象。
  • SecurityUtils 提供便捷方法:获取当前 LoginUser、判断是否管理员、检查菜单/按钮权限、解析上下文中的范围信息等。
  • 典型场景:在 Controller/Service 中快速访问当前用户与权限,减少样板代码。
classDiagram
class LoginUser {
+userId : String
+username : String
+roles : String[]
+depts : String[]
+permissions : Set~String~
+isAdmin() : boolean
+hasPermission(permission) : boolean
}
class SecurityUtils {
+getCurrentUser() : LoginUser
+getUserId() : String
+checkPermission(permission) : void
+getDataScope() : DataScopeLevel
}
SecurityUtils --> LoginUser : "使用"

图表来源

  • LoginUser.java:1-200
  • SecurityUtils.java:1-200

章节来源

  • LoginUser.java:1-200
  • SecurityUtils.java:1-200

数据权限控制实现原理

  • 拦截器机制:DataScopeInterceptor 在方法执行前解析注解与上下文,设置 DataVisibilityContext 中的数据范围。
  • SQL 过滤:CrmSqlInjector 在 MyBatis-Plus 执行 SQL 前,根据 DataVisibilityContext 动态注入 WHERE 条件,实现行级数据隔离。
  • 用户权限验证:JwtAuthenticationFilter 与 TokenService 完成认证;PermissionConfig 与 SecurityConfig 管理接口级鉴权;AuthService 与 Sys*Mapper 加载角色、部门、菜单等权限数据。
sequenceDiagram
participant Controller as "Controller"
participant Interceptor as "DataScopeInterceptor"
participant Context as "DataVisibilityContext"
participant MP as "MyBatis-Plus"
participant Injector as "CrmSqlInjector"
participant Mapper as "Sys*Mapper"
Controller->>Interceptor : "进入受保护方法"
Interceptor->>Context : "设置数据范围"
Controller->>MP : "调用Service/Mapper"
MP->>Injector : "拦截SQL"
Injector->>Context : "读取数据范围"
Injector->>Mapper : "注入过滤条件执行"
Mapper-->>MP : "返回受限结果集"

图表来源

  • DataScopeInterceptor.java:1-200
  • DataVisibilityContext.java:1-200
  • CrmSqlInjector.java:1-200
  • SysRoleMapper.java:1-200
  • SysDeptMapper.java:1-200
  • SysUserRoleMapper.java:1-200
  • SysUserDeptMapper.java:1-200

章节来源

  • DataScopeInterceptor.java:1-200
  • CrmSqlInjector.java:1-200
  • JwtAuthenticationFilter.java:1-200
  • TokenService.java:1-200
  • PermissionConfig.java:1-200
  • SecurityConfig.java:1-200
  • AuthService.java:1-200
  • AuthServiceImpl.java:1-200
  • SysRoleMapper.java:1-200
  • SysDeptMapper.java:1-200
  • SysUserRoleMapper.java:1-200
  • SysUserDeptMapper.java:1-200

数据范围表映射 DataScopeTables

  • DataScopeTables 维护需要应用数据范围过滤的表名与字段映射,确保 SQL 注入器能精准定位目标表与列。
  • 支持按表维度配置不同的过滤字段(如 owner_id、dept_id 等),提高灵活性。

章节来源

  • DataScopeTables.java:1-200

认证与授权流程

  • JwtAuthenticationFilter 从请求头提取 Token,调用 TokenService 校验并构建 AuthLoginUser。
  • SecurityConfig 注册过滤器与全局安全策略;PermissionConfig 定义接口级权限规则。
  • AuthServiceImpl 与 Sys*Mapper 协作加载用户角色、部门、菜单等权限数据,供后续鉴权使用。
sequenceDiagram
participant Client as "客户端"
participant Filter as "JwtAuthenticationFilter"
participant Token as "TokenService"
participant Config as "SecurityConfig"
participant Perm as "PermissionConfig"
participant Service as "AuthService"
participant Mapper as "Sys*Mapper"
Client->>Filter : "HTTP 请求(含Token)"
Filter->>Token : "校验Token"
Token-->>Filter : "返回用户信息"
Filter-->>Client : "放行"
Client->>Perm : "访问受保护接口"
Perm->>Service : "校验角色/菜单权限"
Service->>Mapper : "查询用户权限数据"
Mapper-->>Service : "返回权限集合"
Service-->>Perm : "鉴权结果"
Perm-->>Client : "允许/拒绝"

图表来源

  • JwtAuthenticationFilter.java:1-200
  • TokenService.java:1-200
  • SecurityConfig.java:1-200
  • PermissionConfig.java:1-200
  • AuthService.java:1-200
  • AuthServiceImpl.java:1-200
  • SysRoleMapper.java:1-200
  • SysMenuMapper.java:1-200
  • SysDeptMapper.java:1-200
  • SysUserRoleMapper.java:1-200
  • SysUserDeptMapper.java:1-200

章节来源

  • JwtAuthenticationFilter.java:1-200
  • TokenService.java:1-200
  • SecurityConfig.java:1-200
  • PermissionConfig.java:1-200
  • AuthService.java:1-200
  • AuthServiceImpl.java:1-200
  • SysRoleMapper.java:1-200
  • SysMenuMapper.java:1-200
  • SysDeptMapper.java:1-200
  • SysUserRoleMapper.java:1-200
  • SysUserDeptMapper.java:1-200

数据范围注解 DataScope 与辅助 DataScopeHelper

  • DataScope 注解用于在方法或类级别声明数据范围策略,可与 DataOwnership 组合使用。
  • DataScopeHelper 提供统一的范围计算逻辑,支持合并多个来源的权限、生成 SQL 片段、处理边界条件。

章节来源

  • DataScope.java:1-200
  • DataScopeHelper.java:1-200

MyBatis-Plus 集成与 SQL 注入器

  • MybatisPlusConfig 启用自定义 SQL 注入器 CrmSqlInjector。
  • CrmSqlInjector 在 SELECT/UPDATE/DELETE 前拦截,根据 DataVisibilityContext 注入 WHERE 条件,实现无侵入式数据权限控制。

章节来源

  • MybatisPlusConfig.java:1-200
  • CrmSqlInjector.java:1-200

集成测试示例

  • DataScopeIntegrationTest 展示了如何在测试环境中验证数据范围过滤的正确性,包括不同用户与部门下的数据可见性。

章节来源

  • DataScopeIntegrationTest.java:1-200

依赖关系分析

  • 低耦合高内聚:DataOwnership、DataScopeLevel、DataVisibilityContext 位于 crm-base,被 crm-auth 复用,职责清晰。
  • 关键依赖链:
    • JwtAuthenticationFilter → TokenService → AuthLoginUser
    • DataScopeInterceptor → DataVisibilityContext → CrmSqlInjector → Sys*Mapper
    • PermissionConfig → SecurityConfig → 全局安全策略
graph LR
Base["crm-base"] --> Auth["crm-auth"]
Base --> |"DataOwnership/DataScopeLevel/DataVisibilityContext"| Auth
Auth --> |"JwtAuthenticationFilter/TokenService/DataScopeInterceptor"| Base
Auth --> |"Sys*Mapper"| DB[("数据库")]

图表来源

  • DataOwnership.java:1-200
  • DataScopeLevel.java:1-200
  • DataVisibilityContext.java:1-200
  • JwtAuthenticationFilter.java:1-200
  • TokenService.java:1-200
  • DataScopeInterceptor.java:1-200
  • SysRoleMapper.java:1-200
  • SysDeptMapper.java:1-200
  • SysUserRoleMapper.java:1-200
  • SysUserDeptMapper.java:1-200

章节来源

  • DataOwnership.java:1-200
  • DataScopeLevel.java:1-200
  • DataVisibilityContext.java:1-200
  • JwtAuthenticationFilter.java:1-200
  • TokenService.java:1-200
  • DataScopeInterceptor.java:1-200
  • SysRoleMapper.java:1-200
  • SysDeptMapper.java:1-200
  • SysUserRoleMapper.java:1-200
  • SysUserDeptMapper.java:1-200

性能考量

  • 上下文管理:避免在高频路径中频繁创建/销毁对象,合理使用 ThreadLocal 并在 finally 块中清理。
  • SQL 注入:尽量将数据范围条件下推到数据库层,减少应用层过滤开销;合理索引 dept_id、owner_id 等字段。
  • 权限缓存:对角色、部门、菜单等静态或低频变更数据引入缓存,降低数据库压力。
  • 拦截器链:最小化拦截器逻辑,避免复杂计算阻塞请求链路。

故障排查指南

  • Token 无效或过期:检查 TokenService 的签名算法、密钥配置与有效期设置;确认 JwtAuthenticationFilter 是否正确解析请求头。
  • 数据范围不生效:确认 DataScopeInterceptor 是否注册;检查 DataScopeTables 是否包含目标表;验证 DataVisibilityContext 是否被正确设置与清理。
  • 权限校验失败:核对 PermissionConfig 的路径白名单与鉴权规则;检查 AuthServiceImpl 与 Sys*Mapper 的权限数据加载逻辑。
  • SQL 注入异常:查看 CrmSqlInjector 的注入逻辑与 DataScopeHelper 的条件生成;确认 MybatisPlusConfig 是否启用自定义注入器。

章节来源

  • TokenService.java:1-200
  • JwtAuthenticationFilter.java:1-200
  • DataScopeInterceptor.java:1-200
  • DataScopeTables.java:1-200
  • DataVisibilityContext.java:1-200
  • PermissionConfig.java:1-200
  • AuthServiceImpl.java:1-200
  • SysRoleMapper.java:1-200
  • SysDeptMapper.java:1-200
  • SysUserRoleMapper.java:1-200
  • SysUserDeptMapper.java:1-200
  • CrmSqlInjector.java:1-200
  • MybatisPlusConfig.java:1-200

结论

本安全框架通过注解驱动的 DataOwnership 与 DataScopeLevel 实现灵活的数据范围控制,结合 DataVisibilityContext 与 CrmSqlInjector 完成无侵入式 SQL 过滤;JwtAuthenticationFilter 与 TokenService 保障认证安全;PermissionConfig 与 SecurityConfig 统一管理接口鉴权。建议在生产环境结合缓存与索引优化性能,并通过集成测试覆盖典型场景。

附录

  • 最佳实践
    • 在 Service 层使用 DataOwnership/DataScope 注解声明数据范围,避免在业务逻辑中硬编码过滤条件。
    • 将静态权限数据(角色、菜单、部门树)缓存至 Redis,缩短鉴权路径。
    • 为 dept_id、owner_id、tenant_id 等字段建立合适索引,提升数据范围过滤性能。
    • 在单元测试中使用 DataScopeIntegrationTest 模式验证数据可见性与权限控制。
  • 自定义扩展
    • 新增数据范围级别:扩展 DataScopeLevel 枚举,并在 DataScopeHelper 中补充对应 SQL 生成逻辑。
    • 自定义权限策略:实现自己的 PermissionChecker 并在 PermissionConfig 中注册。
    • 扩展 SQL 注入器:继承 CrmSqlInjector 的逻辑,增加新的过滤维度(如项目、客户等)。