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.
 
 
 
 
 
 

23 KiB

用户安全信息

**本文引用的文件** - [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) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.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) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [SystemController.java](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java) - [AuthUser.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthUser.java) - [SysRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRole.java) - [SysDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java) - [SysMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java) - [SysUserRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserRole.java) - [SysUserDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java) - [PermissionServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java) - [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java) - [AuthUserMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/AuthUserMapper.java) - [SysRoleMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysRoleMapper.java) - [SysDeptMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysDeptMapper.java) - [SysMenuMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysMenuMapper.java)

目录

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

简介

本文件面向“用户安全信息”主题,聚焦以下目标:

  • 深入解析 LoginUser 用户信息模型的结构与字段含义(身份、角色权限、部门信息等)。
  • 详解 SecurityUtils 工具类提供的安全操作方法(获取当前登录用户、检查权限、验证角色等)。
  • 提供在 Controller 与 Service 层正确使用这些工具方法的完整示例路径。
  • 总结用户信息缓存策略与安全最佳实践,并给出常见问题与解决方案。

项目结构

本项目采用多模块设计,安全相关能力主要分布在 crm-base(基础安全能力)与 crm-auth(认证授权实现)两个模块中:

  • crm-base:定义通用安全上下文、数据可见性、权限辅助工具等。
  • crm-auth:实现登录、鉴权、JWT 过滤、令牌服务、权限服务等。
graph TB
subgraph "crm-base"
base_login["LoginUser"]
base_utils["SecurityUtils"]
base_scope["DataScopeHelper / DataVisibilityContext / DataScope注解"]
end
subgraph "crm-auth"
auth_login_user["AuthLoginUser"]
token_svc["TokenService"]
jwt_filter["JwtAuthenticationFilter"]
perm_svc["PermissionServiceImpl"]
controllers["AuthController / SystemController"]
entities["AuthUser / SysRole / SysDept / SysMenu / 关联表"]
mappers["*Mapper 接口"]
end
controllers --> jwt_filter
jwt_filter --> token_svc
token_svc --> base_login
base_login --> base_utils
base_utils --> base_scope
perm_svc --> entities
perm_svc --> mappers
controllers --> perm_svc

图表来源

  • LoginUser.java:1-200
  • SecurityUtils.java:1-200
  • AuthLoginUser.java:1-200
  • TokenService.java:1-200
  • JwtAuthenticationFilter.java:1-200
  • DataScopeHelper.java:1-200
  • DataVisibilityContext.java:1-200
  • DataScope.java:1-200
  • AuthController.java:1-200
  • SystemController.java:1-200
  • PermissionServiceImpl.java:1-200

章节来源

  • LoginUser.java:1-200
  • SecurityUtils.java:1-200
  • AuthLoginUser.java:1-200
  • TokenService.java:1-200
  • JwtAuthenticationFilter.java:1-200
  • DataScopeHelper.java:1-200
  • DataVisibilityContext.java:1-200
  • DataScope.java:1-200
  • AuthController.java:1-200
  • SystemController.java:1-200
  • PermissionServiceImpl.java:1-200

核心组件

  • LoginUser:统一的用户安全上下文对象,承载用户身份、角色、权限、部门、租户等关键信息,作为跨层传递的安全主体。
  • AuthLoginUser:认证模块对 LoginUser 的具体实现或扩展,封装认证态下的额外属性。
  • SecurityUtils:安全工具类,提供获取当前登录用户、判断是否登录、校验角色/权限、获取数据范围等便捷方法。
  • TokenService:负责 JWT 的生成、解析、刷新与校验,维护会话与用户信息的映射。
  • JwtAuthenticationFilter:拦截请求,解析 Token,构建 Spring Security 的认证上下文,并将 LoginUser 注入到线程上下文。
  • DataScopeHelper / DataVisibilityContext / @DataScope:数据权限与数据可见性控制,基于用户角色与部门进行行级数据隔离。

章节来源

  • LoginUser.java:1-200
  • AuthLoginUser.java:1-200
  • SecurityUtils.java:1-200
  • TokenService.java:1-200
  • JwtAuthenticationFilter.java:1-200
  • DataScopeHelper.java:1-200
  • DataVisibilityContext.java:1-200
  • DataScope.java:1-200

架构总览

下图展示了从请求进入、认证、鉴权到业务处理的完整流程,以及用户信息在各层的流转方式。

sequenceDiagram
participant Client as "客户端"
participant API as "控制器(Controller)"
participant Filter as "JwtAuthenticationFilter"
participant Token as "TokenService"
participant Ctx as "SecurityUtils/上下文"
participant Svc as "业务Service"
participant DB as "数据库"
Client->>API : "HTTP 请求(携带Token)"
API->>Filter : "进入过滤器链"
Filter->>Token : "解析并校验Token"
Token-->>Filter : "返回用户信息(LoginUser)"
Filter->>Ctx : "将LoginUser写入线程上下文"
Filter-->>API : "放行请求"
API->>Svc : "调用业务方法"
Svc->>Ctx : "通过SecurityUtils获取当前用户"
Svc->>DB : "执行数据访问(受数据权限影响)"
DB-->>Svc : "返回结果"
Svc-->>API : "返回业务结果"
API-->>Client : "响应"

图表来源

  • JwtAuthenticationFilter.java:1-200
  • TokenService.java:1-200
  • SecurityUtils.java:1-200
  • AuthController.java:1-200
  • SystemController.java:1-200

详细组件分析

LoginUser 用户信息模型

  • 作用:统一承载当前登录用户的身份信息、角色、权限、部门、租户等,贯穿认证、鉴权与业务处理全链路。
  • 关键字段(概念说明):
    • 用户标识:唯一用户ID,用于跨系统识别用户。
    • 用户名/昵称:展示用名称。
    • 角色集合:用户拥有的角色列表,用于权限判定。
    • 权限集合:细粒度操作权限(如菜单、按钮、接口级)。
    • 部门信息:用户所属部门及层级,支撑数据范围控制。
    • 其他扩展:租户ID、设备信息、登录IP等。
  • 使用建议:
    • 在 Controller/Service 中通过 SecurityUtils 获取 LoginUser,避免直接构造。
    • 敏感字段(如密码、密钥)不应出现在 LoginUser 中。
    • 如需扩展,优先在 AuthLoginUser 中扩展,保持基础模型稳定。

章节来源

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

SecurityUtils 工具类

  • 功能概览:
    • 获取当前登录用户:从线程上下文读取 LoginUser。
    • 是否已登录:判断上下文是否存在有效用户。
    • 角色/权限校验:快速判断用户是否具备某角色或权限。
    • 数据范围辅助:结合 @DataScope 注解与 DataScopeHelper 生成 SQL 条件。
  • 典型用法(以路径引用代替代码片段):
    • 获取当前用户:参考 SecurityUtils.java:1-200
    • 校验角色:参考 SecurityUtils.java:1-200
    • 校验权限:参考 SecurityUtils.java:1-200
    • 数据范围:参考 DataScopeHelper.java:1-200

章节来源

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

认证与鉴权流程(JwtAuthenticationFilter + TokenService)

  • 流程要点:
    • 过滤器从请求头提取 Token。
    • TokenService 解析并校验 Token,若有效则构建 LoginUser。
    • 将 LoginUser 写入线程上下文,供后续业务使用。
    • 若无效或缺失,返回未认证错误。
  • 时序图(见上文“架构总览”),关键节点对应文件如下:
    • 过滤器:JwtAuthenticationFilter.java:1-200
    • 令牌服务:TokenService.java:1-200

章节来源

  • JwtAuthenticationFilter.java:1-200
  • TokenService.java:1-200

权限与数据范围(@DataScope + DataScopeHelper)

  • 数据权限注解:通过 @DataScope 声明数据范围级别(如全部、本部门、本人等)。
  • 数据可见性上下文:DataVisibilityContext 维护当前请求的数据可见范围。
  • 数据范围助手:DataScopeHelper 根据上下文与用户角色/部门生成 SQL 过滤条件。
  • 使用建议:
    • 在需要数据隔离的 Service 方法上添加 @DataScope。
    • 查询前确保上下文正确设置(通常由过滤器或拦截器完成)。
    • 避免在复杂 SQL 中绕过数据范围。
flowchart TD
Start(["进入带@DataScope的方法"]) --> CheckCtx["检查数据可见性上下文"]
CheckCtx --> HasCtx{"上下文存在?"}
HasCtx --> |否| InitCtx["初始化默认数据范围"]
HasCtx --> |是| BuildCond["根据用户角色/部门构建SQL条件"]
InitCtx --> BuildCond
BuildCond --> Apply["应用到查询语句"]
Apply --> End(["返回受限结果集"])

图表来源

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

章节来源

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

控制器与服务层使用示例(路径引用)

  • Controller 层:
    • 获取当前用户:参考 AuthController.java:1-200
    • 权限校验:参考 SystemController.java:1-200
  • Service 层:
    • 使用 SecurityUtils 获取用户并进行业务判断:参考 PermissionServiceImpl.java:1-200
    • 数据范围控制:参考 DataScopeHelper.java:1-200

章节来源

  • AuthController.java:1-200
  • SystemController.java:1-200
  • PermissionServiceImpl.java:1-200
  • DataScopeHelper.java:1-200

实体与关系(用户、角色、部门、菜单)

  • 实体关系概览:
    • 用户与角色:多对多(通过关联表)。
    • 用户与部门:多对多(通过关联表)。
    • 角色与菜单:多对多(通过关联表)。
  • ER 图(概念示意):
erDiagram
AUTH_USER {
uuid id PK
string username
string nickname
int status
timestamp created_at
timestamp updated_at
}
SYS_ROLE {
uuid id PK
string role_code
string role_name
int status
}
SYS_DEPT {
uuid id PK
string dept_name
int parent_id
int sort_order
}
SYS_MENU {
uuid id PK
string menu_code
string menu_name
int type
}
SYS_USER_ROLE {
uuid user_id FK
uuid role_id FK
}
SYS_USER_DEPT {
uuid user_id FK
uuid dept_id FK
}
SYS_ROLE_MENU {
uuid role_id FK
uuid menu_id FK
}
AUTH_USER ||--o{ SYS_USER_ROLE : "拥有"
SYS_ROLE ||--o{ SYS_USER_ROLE : "被拥有"
AUTH_USER ||--o{ SYS_USER_DEPT : "属于"
SYS_DEPT ||--o{ SYS_USER_DEPT : "包含"
SYS_ROLE ||--o{ SYS_ROLE_MENU : "配置"
SYS_MENU ||--o{ SYS_ROLE_MENU : "被配置"

图表来源

  • AuthUser.java:1-200
  • SysRole.java:1-200
  • SysDept.java:1-200
  • SysMenu.java:1-200
  • SysUserRole.java:1-200
  • SysUserDept.java:1-200
  • SysRoleMenu.java:1-200

章节来源

  • AuthUser.java:1-200
  • SysRole.java:1-200
  • SysDept.java:1-200
  • SysMenu.java:1-200
  • SysUserRole.java:1-200
  • SysUserDept.java:1-200
  • SysRoleMenu.java:1-200

依赖关系分析

  • 模块间依赖:
    • crm-auth 依赖 crm-base 的安全基础能力(LoginUser、SecurityUtils、数据范围)。
    • 控制器依赖过滤器与令牌服务完成认证;业务层依赖 SecurityUtils 与数据范围工具。
  • 运行时依赖:
    • TokenService 依赖持久化存储(用户、角色、权限、部门)与缓存(可选)。
    • 数据范围依赖 MyBatis/MyBatis-Plus 的动态 SQL 拼接。
graph LR
base["crm-base<br/>LoginUser/SecurityUtils/DataScope"] --> auth["crm-auth<br/>AuthLoginUser/TokenService/JwtFilter"]
auth --> controllers["Controllers"]
auth --> services["Services"]
services --> db["Database"]

图表来源

  • LoginUser.java:1-200
  • SecurityUtils.java:1-200
  • AuthLoginUser.java:1-200
  • TokenService.java:1-200
  • JwtAuthenticationFilter.java:1-200

章节来源

  • LoginUser.java:1-200
  • SecurityUtils.java:1-200
  • AuthLoginUser.java:1-200
  • TokenService.java:1-200
  • JwtAuthenticationFilter.java:1-200

性能考虑

  • 用户信息缓存:
    • 建议在 Redis 中缓存 LoginUser 及其角色/权限,减少频繁查库。
    • 缓存键设计:user:{userId}:profile、role:{roleId}:perms、dept:{deptId}:info。
    • 失效策略:用户信息变更时主动失效;设置合理过期时间(如 30 分钟)。
  • 数据范围优化:
    • 尽量使用索引字段(如 dept_id、owner_id)进行过滤。
    • 避免在大数据集上使用复杂子查询,必要时物化视图或预聚合。
  • 令牌校验:
    • 本地签名校验优先,避免每次校验都落库。
    • 黑名单机制需配合缓存(Redis)实现高效查找。

[本节为通用指导,不直接分析具体文件]

故障排查指南

  • 常见安全问题与解决:
    • 未登录或 Token 无效:检查 JwtAuthenticationFilter 与 TokenService 的解析逻辑与异常处理。
    • 权限不足:确认用户角色与权限配置是否正确,检查 @DataScope 注解与数据范围上下文。
    • 数据越权:核查数据范围 SQL 是否正确注入,避免绕过。
    • 并发与一致性:用户信息更新后及时清理缓存,避免脏读。
  • 定位步骤:
    • 查看过滤器日志与异常堆栈。
    • 打印 SecurityUtils 获取的 LoginUser 内容,确认上下文是否正确。
    • 检查 Mapper 生成的 SQL 是否包含数据范围条件。

章节来源

  • JwtAuthenticationFilter.java:1-200
  • TokenService.java:1-200
  • DataScopeHelper.java:1-200
  • DataVisibilityContext.java:1-200

结论

  • LoginUser 是贯穿认证、鉴权与业务的核心载体,应保持稳定与最小暴露原则。
  • SecurityUtils 提供统一入口,简化用户信息与权限判断的使用。
  • 数据范围控制通过 @DataScope 与 DataScopeHelper 实现,确保行级数据安全。
  • 合理的缓存策略与严格的异常处理是保障性能与安全的关键。

[本节为总结,不直接分析具体文件]

附录

  • 常用路径参考:
    • 获取当前用户:SecurityUtils.java:1-200
    • 校验角色/权限:SecurityUtils.java:1-200
    • 数据范围注解:DataScope.java:1-200
    • 数据范围助手:DataScopeHelper.java:1-200
    • 认证过滤器:JwtAuthenticationFilter.java:1-200
    • 令牌服务:TokenService.java:1-200
    • 控制器示例:AuthController.java:1-200、SystemController.java:1-200
    • 权限服务:PermissionServiceImpl.java:1-200

[本节为附录,不直接分析具体文件]