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.
 
 
 
 
 
 

48 KiB

安全配置与过滤器

**本文引用的文件** - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [WebMvcConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/WebMvcConfig.java) - [ApiPermissionInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionInterceptor.java) - [ApiPermissionCache.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionCache.java) - [ApiPermissionRule.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionRule.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) - [SecurityExceptionHandlers.java](file://crm-auth/src/main/java/com/crm/auth/security/SecurityExceptionHandlers.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) - [DataInitializer.java](file://crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java) - [CorsConfig.java](file://crm-base/src/main/java/com/crm/base/config/CorsConfig.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.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) - [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) - [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) - [ResourceController.java](file://crm-auth/src/main/java/com/crm/auth/controller/ResourceController.java) - [IResourceService.java](file://crm-auth/src/main/java/com/crm/auth/service/IResourceService.java) - [ResourceServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/ResourceServiceImpl.java) - [ResourceNode.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/ResourceNode.java) - [AuthProperties.java](file://crm-auth/src/main/java/com/crm/auth/config/AuthProperties.java) - [AuthConstants.java](file://crm-auth/src/main/java/com/crm/auth/constant/AuthConstants.java) - [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-auth/src/main/resources/application.yml) - [PermissionResolver.java](file://crm-auth/src/main/java/com/crm/auth/security/PermissionResolver.java) - [PermissionResolverImpl.java](file://crm-auth/src/main/java/com/crm/auth/security/PermissionResolverImpl.java) - [PermissionGrant.java](file://crm-auth/src/main/java/com/crm/auth/security/PermissionGrant.java)

更新摘要

变更内容

  • 新增API权限拦截器架构:引入WebMvcConfig、ApiPermissionInterceptor、ApiPermissionCache和ApiPermissionRule,实现基于URL模式的动态权限验证
  • 增强SecurityFilterChain:集成新的API权限验证机制,形成"认证→授权→数据权限"的完整安全链
  • 改进权限验证流程:通过Caffeine缓存提升API权限匹配性能,支持Ant风格路径匹配
  • fail-open策略:未注册规则的接口默认放行,已注册规则严格校验用户权限

目录

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

简介

本文件围绕 CRM 后端项目的安全配置与数据权限过滤进行系统化说明,重点覆盖:

  • Spring Security 配置与安全策略(认证、授权、跨域、异常处理)
  • 自定义过滤器链(JWT 认证过滤器、API权限拦截器、数据权限拦截器)
  • API权限动态验证机制(基于URL模式匹配、Caffeine缓存、Ant路径匹配)
  • 数据权限拦截器实现(注解驱动、表级映射、上下文传递)
  • 初始化数据配置(角色、菜单、用户等基础数据)
  • 安全异常处理与统一返回
  • 跨域配置与最佳实践
  • 已更新:新增API权限拦截器架构,实现基于URL模式的动态权限验证

目标是帮助开发者快速理解并正确使用系统的安全与数据权限能力。

项目结构

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

  • crm-auth:Spring Security 配置、JWT 认证、API权限拦截器、数据权限拦截器、权限配置、初始化数据、资源管理接口
  • crm-base:跨域配置、全局异常处理、数据权限注解与工具、登录用户上下文
graph TB
subgraph "crm-auth"
A["SecurityConfig<br/>安全配置"]
B["WebMvcConfig<br/>MVC配置"]
C["ApiPermissionInterceptor<br/>API权限拦截器"]
D["ApiPermissionCache<br/>API权限缓存"]
E["ApiPermissionRule<br/>权限规则"]
F["JwtAuthenticationFilter<br/>JWT认证过滤器"]
G["DataScopeInterceptor<br/>数据权限拦截器"]
H["DataScopeTables<br/>表权限映射"]
I["TokenService<br/>令牌服务"]
J["PermissionConfig<br/>权限配置"]
K["DataInitializer<br/>初始化数据"]
L["SecurityExceptionHandlers<br/>安全异常处理"]
M["ResourceController<br/>资源管理控制器"]
N["IResourceService<br/>资源管理服务"]
O["ResourceServiceImpl<br/>资源服务实现"]
P["PermissionResolver<br/>权限解析接口"]
Q["PermissionResolverImpl<br/>权限解析实现"]
R["PermissionGrant<br/>权限授予对象"]
end
subgraph "crm-base"
S["CorsConfig<br/>跨域配置"]
T["GlobalExceptionHandlerAdvice<br/>全局异常处理"]
U["DataScope<br/>数据权限注解"]
V["DataScopeHelper<br/>数据权限工具"]
W["DataVisibilityContext<br/>可见性上下文"]
X["DataOwnership<br/>数据所有权注解"]
Y["DataScopeLevel<br/>数据范围级别"]
Z["LoginUser<br/>登录用户模型"]
AA["SecurityUtils<br/>安全工具"]
end
A --> B
A --> F
A --> G
A --> J
A --> L
A --> M
B --> C
C --> D
D --> E
F --> P
P --> Q
Q --> R
G --> H
G --> V
G --> W
F --> I
M --> N
N --> O
S --> A
T --> A

图表来源

  • SecurityConfig.java
  • WebMvcConfig.java
  • ApiPermissionInterceptor.java
  • ApiPermissionCache.java
  • ApiPermissionRule.java
  • JwtAuthenticationFilter.java
  • DataScopeInterceptor.java
  • DataScopeTables.java
  • TokenService.java
  • PermissionConfig.java
  • DataInitializer.java
  • SecurityExceptionHandlers.java
  • ResourceController.java
  • IResourceService.java
  • ResourceServiceImpl.java
  • CorsConfig.java
  • GlobalExceptionHandlerAdvice.java
  • DataScope.java
  • DataScopeHelper.java
  • DataVisibilityContext.java
  • DataOwnership.java
  • DataScopeLevel.java
  • LoginUser.java
  • SecurityUtils.java
  • PermissionResolver.java
  • PermissionResolverImpl.java
  • PermissionGrant.java

章节来源

  • SecurityConfig.java
  • WebMvcConfig.java
  • ApiPermissionInterceptor.java
  • ResourceController.java
  • CorsConfig.java
  • GlobalExceptionHandlerAdvice.java

核心组件

  • SecurityConfig:集中定义 Spring Security 策略,包括放行路径、鉴权规则、过滤器链装配、跨域与异常处理器集成。所有接口现在都需要认证
  • WebMvcConfig:新增 - MVC配置类,注册API权限拦截器,在Spring Security之后、Controller之前执行。
  • ApiPermissionInterceptor:新增 - 动态权限拦截器,基于URL模式匹配和用户权限进行细粒度控制,支持Ant风格通配符。
  • ApiPermissionCache:新增 - API权限规则缓存,使用Caffeine缓存sys_menu中的button节点,提供高性能的权限匹配。
  • ApiPermissionRule:新增 - 权限规则记录类,封装URL模式和对应权限码的映射关系。
  • JwtAuthenticationFilter:已简化 - 从请求头提取 JWT 令牌,通过单一的 permissionResolver.resolve() 方法获取完整的授权信息,然后一次性构建 Authentication 对象并设置到 SecurityContext。
  • DataScopeInterceptor:基于 @DataScope 注解与 DataScopeTables 映射,动态拼装 SQL 条件,实现行级数据权限控制。
  • TokenService:提供令牌生成、校验、刷新等能力,支撑无状态认证。
  • PermissionResolver:新增 - 权限解析引擎接口,定义 resolve() 和 visibleMenuTree() 方法,统一处理用户权限、角色和数据可见性的解析。
  • PermissionResolverImpl:新增 - 权限解析引擎实现,封装了「用户 → 角色 → 授权 → 资源」的完整查询链,支持 fail-closed 策略。
  • PermissionGrant:新增 - 权限授予对象,包含数据可见性、权限码并集和角色编码,提供 asAuthorities() 方法转换为 Spring Security authorities。
  • PermissionConfig:权限相关的配置项(如角色-菜单映射、接口权限白名单)。
  • DataInitializer:启动时初始化基础数据(角色、菜单、用户、部门等),保障系统可用。
  • SecurityExceptionHandlers:统一捕获认证与授权异常,转换为标准错误响应。
  • ResourceController:已重构为标准化的动作后缀模式,需要ADMIN角色权限才能访问
  • CorsConfig:跨域配置,允许前端调用。
  • GlobalExceptionHandlerAdvice:全局异常处理,统一错误码与消息。
  • 数据权限注解与工具:@DataScope、@DataOwnership、DataScopeHelper、DataVisibilityContext、DataScopeLevel、LoginUser、SecurityUtils。

章节来源

  • SecurityConfig.java
  • WebMvcConfig.java
  • ApiPermissionInterceptor.java
  • ApiPermissionCache.java
  • ApiPermissionRule.java
  • ResourceController.java
  • JwtAuthenticationFilter.java
  • DataScopeInterceptor.java
  • DataScopeTables.java
  • TokenService.java
  • PermissionConfig.java
  • DataInitializer.java
  • SecurityExceptionHandlers.java
  • CorsConfig.java
  • GlobalExceptionHandlerAdvice.java
  • DataScope.java
  • DataScopeHelper.java
  • DataVisibilityContext.java
  • DataOwnership.java
  • DataScopeLevel.java
  • LoginUser.java
  • SecurityUtils.java
  • PermissionResolver.java
  • PermissionResolverImpl.java
  • PermissionGrant.java

架构总览

下图展示了典型请求在安全与数据权限层面的处理流程:客户端请求进入后,先经过跨域与全局异常处理,再进入 Spring Security 过滤器链;未认证的请求由简化的 JWT 过滤器处理,通过统一的权限解析引擎获取完整的授权信息,认证成功后进入MVC层;此时API权限拦截器根据URL模式匹配用户权限,最后进入业务控制器;在执行数据访问前,数据权限拦截器根据注解与表映射动态注入 WHERE 条件,确保数据隔离。特别地,/api/resources/ 路径现在需要完整的认证和 ADMIN 角色权限才能访问,这是安全强化的重要特性**。

sequenceDiagram
participant Client as "客户端"
participant Web as "Web层"
participant Security as "Spring Security"
participant Jwt as "JwtAuthenticationFilter"
participant Resolver as "PermissionResolver"
participant Mvc as "WebMvcConfig"
participant ApiPerm as "ApiPermissionInterceptor"
participant Controller as "ResourceController"
participant Interceptor as "DataScopeInterceptor"
participant DB as "数据库"
Client->>Web : HTTP 请求
Web->>Security : 进入过滤器链
alt 资源管理端点 (/api/resources/**)
Security->>Security : 检查ADMIN角色权限
Security-->>Jwt : 需要认证和角色验证
Jwt->>Jwt : 解析JWT令牌
Jwt->>Resolver : 调用resolve()获取完整授权
Resolver-->>Jwt : 返回PermissionGrant(可见性+权限+角色)
Jwt->>Jwt : 设置DataVisibilityContext
Jwt->>Jwt : 构建UsernamePasswordAuthenticationToken
Jwt-->>Security : 设置SecurityContext
Security-->>Mvc : 放行至MVC层
Mvc->>ApiPerm : API权限拦截器
ApiPerm->>ApiPerm : URL模式匹配
ApiPerm->>ApiPerm : 权限码验证
ApiPerm-->>Controller : 权限验证通过
else 其他受保护接口
Security->>Jwt : 解析JWT并构建认证
Jwt->>Resolver : 调用resolve()获取授权
Resolver-->>Jwt : 返回完整授权信息
Jwt-->>Security : 设置SecurityContext
Security-->>Mvc : 放行至MVC层
Mvc->>ApiPerm : API权限拦截器
ApiPerm-->>Controller : 权限验证通过
else 公开接口
Security-->>Mvc : 直接放行
Mvc-->>Controller : 直接放行
end
Controller->>Interceptor : 执行方法前触发拦截
Interceptor->>Interceptor : 读取@DataScope与表映射
Interceptor-->>Controller : 注入SQL条件
Controller->>DB : 执行查询/更新
DB-->>Controller : 返回结果
Controller-->>Client : 统一响应

图表来源

  • SecurityConfig.java
  • WebMvcConfig.java
  • ApiPermissionInterceptor.java
  • ApiPermissionCache.java
  • ResourceController.java
  • JwtAuthenticationFilter.java
  • DataScopeInterceptor.java
  • DataScopeTables.java
  • PermissionResolver.java
  • PermissionResolverImpl.java

详细组件分析

SecurityConfig 安全策略配置

  • 功能要点
    • 定义放行路径(静态资源、健康检查、开放接口等)仅包含登录接口、文档接口和其他必要公开接口
    • 配置认证与授权规则(按角色或权限标识控制)
    • 装配自定义过滤器(JWT 认证过滤器)
    • 集成跨域配置与异常处理器
    • 禁用默认表单登录/CSRF(适用于前后端分离场景)
  • 关键配置项
    • 白名单路径集合:仅包含登录接口、文档接口和其他必要公开接口
    • 需要鉴权的 URL 模式与对应权限
    • 过滤器链顺序(CORS -> 认证 -> 授权)
    • 异常处理器注册
  • 使用示例
    • 新增需鉴权接口:在权限配置中添加 URL 与权限标识
    • 新增放行接口:添加到白名单列表(不推荐用于敏感接口)
    • 调整跨域策略:通过 CorsConfig 统一配置

重要更新 资源管理端点 (/api/resources/**) 已从白名单中移除,现在需要完整的认证和 ADMIN 角色权限才能访问,这符合 CRITICAL 安全规范要求。

章节来源

  • SecurityConfig.java
  • PermissionConfig.java
  • CorsConfig.java

WebMvcConfig MVC配置(新增)

  • 新增组件:MVC配置类,负责注册API权限拦截器
  • 功能要点
    • 实现WebMvcConfigurer接口,重写addInterceptors方法
    • 注册ApiPermissionInterceptor到所有/api/**路径
    • 拦截器在Spring Security过滤器之后、Controller之前执行
    • 确保API权限验证在业务逻辑执行前完成
  • 执行时机
    • Spring Security认证通过后
    • Controller方法调用前
    • 数据权限拦截器之前

章节来源

  • WebMvcConfig.java

ApiPermissionInterceptor API权限拦截器(新增)

  • 新增组件:动态权限验证拦截器,基于URL模式匹配进行细粒度权限控制
  • 功能要点
    • 实现HandlerInterceptor接口,重写preHandle方法
    • 使用AntPathMatcher进行URL模式匹配(支持*和**通配符)
    • 从SecurityContext获取当前用户权限集合
    • 支持fail-open策略:未匹配规则直接放行
    • 匹配到规则但无权限时返回403状态码
  • 处理流程
    • 获取请求URI和所有匹配的权限规则
    • 如果无匹配规则,直接放行(fail-open)
    • 获取当前用户权限集合
    • 检查用户是否拥有任一匹配规则的perms
    • 有权限则放行,无权限返回403
  • 性能优化
    • 使用Caffeine缓存权限规则,避免频繁数据库查询
    • AntPathMatcher预编译,提高匹配效率

章节来源

  • ApiPermissionInterceptor.java
  • ApiPermissionCache.java

ApiPermissionCache API权限缓存(新增)

  • 新增组件:基于Caffeine的进程内缓存,存储API权限规则
  • 功能要点
    • 单key缓存整份规则列表,键名为"apiPermRules"
    • 懒加载机制:首次访问时从数据库加载
    • 支持主动失效:资源树变更后调用invalidate()重建缓存
    • 只加载已启用且配置了apiUrl的button类型菜单
  • 数据来源
    • 从sys_menu表查询menuType=BUTTON且status=enabled的记录
    • 过滤掉apiUrl为空或null的记录
    • 转换为ApiPermissionRule对象列表
  • 缓存策略
    • 使用Caffeine默认配置,适合短期缓存场景
    • 资源树变更时主动失效,保证数据一致性

章节来源

  • ApiPermissionCache.java

ApiPermissionRule 权限规则(新增)

  • 新增组件:权限规则记录类,使用Java record定义
  • 数据结构
    • pattern:Ant风格的URL模式(如/api/users/**)
    • perms:对应的权限码(如crm:user:list)
  • 特点
    • 不可变对象,线程安全
    • 简洁的数据载体,便于序列化和传输

章节来源

  • ApiPermissionRule.java

资源管理接口 ResourceController

  • 功能要点
    • 提供统一的权限资源树管理接口
    • 支持全量资源树查询、节点增删改、图标上传等功能
    • 已重构为标准化的动作后缀模式,需要ADMIN角色权限才能访问
    • 完整的参数校验和业务逻辑验证
  • 核心接口
    • GET /api/resources/list:获取全量资源树(扁平数组)
    • POST /api/resources/saveOrUpdate:新增或编辑节点
    • POST /api/resources/delete:删除节点(含子节点检查,使用表单参数)
    • POST /api/resources/icon/upload:图标文件上传
  • 业务特性
    • 层级约束验证(catalog/menu/button 类型限制)
    • 字段必填校验(编辑模式下 type 不可变更)
    • 级联清理(删除节点时清理角色授权引用)
    • 文件上传校验(格式、大小限制)

重要更新 该控制器现在使用 @PreAuthorize("hasRole('ADMIN')") 注解,确保只有管理员用户才能访问资源管理功能,这是安全强化的关键措施。API端点已重构为标准化的动作后缀模式,所有写操作都使用POST请求配合相应的动作后缀。

章节来源

  • ResourceController.java
  • IResourceService.java
  • ResourceServiceImpl.java
  • ResourceNode.java

JwtAuthenticationFilter 认证过滤器(已简化)

  • 重大简化:移除了双重职责(数据范围初始化和权限创建),现在通过单一的 permissionResolver.resolve() 方法处理认证上下文加载和Spring Security权限创建
  • 功能要点
    • 从请求头提取 JWT 令牌
    • 调用 tokenService.verifyToken() 验证令牌有效性
    • 通过 permissionResolver.resolve() 一次性获取完整的授权信息(数据可见性 + 权限码 + 角色编码)
    • 设置 DataVisibilityContext 用于数据权限控制
    • 将 PermissionGrant 转换为 UsernamePasswordAuthenticationToken 并设置到 SecurityContext
  • 异常处理
    • 令牌无效或缺失时跳过认证,交由后续过滤器处理
    • 权限解析失败采用 fail-closed 策略,直接拒绝请求
  • 使用示例
    • 客户端在请求头携带 Authorization: Bearer
    • 服务端无需额外代码即可获取当前用户信息

更新后的处理流程

  1. 解析JWT令牌并验证
  2. 调用 permissionResolver.resolve(userId) 获取完整的授权信息
  3. 设置 DataVisibilityContext.load(grant.getVisibility())
  4. 转换 PermissionGrant 为 Spring Security authorities
  5. 构建 UsernamePasswordAuthenticationToken 并设置到 SecurityContext

章节来源

  • JwtAuthenticationFilter.java
  • TokenService.java
  • SecurityExceptionHandlers.java
  • PermissionResolver.java
  • PermissionResolverImpl.java
  • PermissionGrant.java

权限解析引擎 PermissionResolver(新增)

  • 新增组件:统一的权限解析引擎,负责处理用户的所有授权事实
  • 功能要点
    • 解析用户的角色、权限码并集和数据可见性
    • 支持 fail-closed 策略,解析失败直接抛出异常
    • 提供 visibleMenuTree() 方法用于前端菜单渲染
  • 核心方法
    • resolve(Long userId):解析用户的完整授权信息,返回 PermissionGrant
    • visibleMenuTree(Long userId):获取用户可见的菜单树(用于前端展示)
  • 处理逻辑
    • 查询用户角色并确定最宽的数据可见性档位
    • 计算用户所属部门集合(主部门 + 兼职部门)
    • 根据数据范围级别展开部门子树
    • 收集所有授权的权限码(button类型且状态启用)
    • 归一化角色编码(添加 ROLE_ 前缀)

章节来源

  • PermissionResolver.java
  • PermissionResolverImpl.java

PermissionGrant 权限授予对象(新增)

  • 新增组件:不可变的权限授予结果对象
  • 功能要点
    • 封装数据可见性、权限码并集和角色编码
    • 提供 asAuthorities() 方法转换为 Spring Security authorities
    • 自动处理角色编码的 ROLE_ 前缀归一化
  • 数据结构
    • visibility:DataVisibility 对象,包含用户ID、部门信息和数据范围
    • permCodes:权限码集合(去重后的 button 权限)
    • roleCodes:角色编码集合(原样存储,不带前缀)

章节来源

  • PermissionGrant.java

DataScopeInterceptor 数据权限拦截器

  • 功能要点
    • 基于 @DataScope 注解识别需要数据权限控制的接口
    • 结合 DataScopeTables 的表名与字段映射,动态拼接 WHERE 条件
    • 支持多种数据范围级别(全部、本部门、本人、自定义)
    • 通过 DataVisibilityContext 传递当前用户的可见范围
  • 处理流程
    • 解析注解参数(表名、主键列、关联列、范围级别)
    • 从登录用户上下文获取组织/角色信息
    • 生成 SQL 片段并注入 MyBatis/MyBatis-Plus 查询
  • 使用示例
    • 在 Service 方法上添加 @DataScope(table="sys_user", scope=DataScopeLevel.DEPT)
    • 查询自动附加 dept_id IN (当前用户所属部门) 的条件

章节来源

  • DataScopeInterceptor.java
  • DataScopeTables.java
  • DataScope.java
  • DataScopeHelper.java
  • DataVisibilityContext.java
  • DataScopeLevel.java

数据权限处理流程图

flowchart TD
Start(["进入拦截器"]) --> CheckAnnotation["检查是否包含@DataScope注解"]
CheckAnnotation --> |否| Skip["跳过数据权限处理"]
CheckAnnotation --> |是| ResolveParams["解析注解参数<br/>表名/字段/范围级别"]
ResolveParams --> LoadContext["加载当前用户上下文"]
LoadContext --> BuildCondition["根据范围级别构建SQL条件"]
BuildCondition --> Inject["注入到查询语句"]
Inject --> End(["继续执行业务逻辑"])
Skip --> End

图表来源

  • DataScopeInterceptor.java
  • DataScopeHelper.java
  • DataVisibilityContext.java

DataScopeTables 表权限映射

  • 功能要点
    • 维护表名与数据权限字段的映射关系
    • 支持主键列、关联列、外键列的配置
    • 便于拦截器快速定位需要注入条件的列
  • 使用示例
    • 为新表添加映射条目,指定主键与关联字段
    • 配合 @DataScope 注解生效

章节来源

  • DataScopeTables.java

TokenService 令牌服务

  • 功能要点
    • 生成 JWT 令牌(含用户标识、角色、权限)
    • 校验令牌签名与有效期
    • 支持刷新与黑名单管理(可选)
  • 使用示例
    • 登录成功后调用生成令牌
    • 后续请求携带令牌进行认证

章节来源

  • TokenService.java
  • JwtAuthenticationFilter.java

SecurityExceptionHandlers 安全异常处理

  • 功能要点
    • 捕获认证失败、授权拒绝等安全异常
    • 统一转换为 Result 响应体(错误码、消息)
    • 与全局异常处理器协作,保证一致性
  • 使用示例
    • 无需业务代码处理,直接返回标准错误响应

章节来源

  • SecurityExceptionHandlers.java
  • GlobalExceptionHandlerAdvice.java

初始化数据配置 DataInitializer

  • 功能要点
    • 启动时检查并插入基础数据(角色、菜单、用户、部门)
    • 避免重复初始化,支持幂等
    • 为权限与数据权限提供初始环境
  • 使用示例
    • 首次部署后自动创建管理员账号与基础菜单

章节来源

  • DataInitializer.java

跨域配置 CorsConfig

  • 功能要点
    • 允许指定域名、方法、头部与凭证
    • 与 Spring Security 集成,确保预检请求放行
  • 使用示例
    • 配置前端域名与允许的请求头

章节来源

  • CorsConfig.java

数据权限注解与工具

  • @DataScope:标注在方法上,声明数据权限策略
  • @DataOwnership:标注实体类,声明数据所有权字段
  • DataScopeHelper:提供 SQL 片段生成与上下文操作
  • DataVisibilityContext:线程局部存储当前可见范围
  • DataScopeLevel:枚举定义数据范围级别
  • LoginUser:登录用户信息模型
  • SecurityUtils:便捷获取当前用户与权限

章节来源

  • DataScope.java
  • DataOwnership.java
  • DataScopeHelper.java
  • DataVisibilityContext.java
  • DataScopeLevel.java
  • LoginUser.java
  • SecurityUtils.java

认证配置 AuthProperties

  • 功能要点
    • 配置 JWT 密钥、有效期等认证参数
    • 支持额外的放行 URL 配置
    • 钉钉第三方认证配置
  • 关键配置项
    • JWT 签名密钥(生产环境必须修改)
    • 登录态有效期(天)
    • 额外放行的 URL 列表
    • 钉钉应用配置(Client ID/Secret)

章节来源

  • AuthProperties.java

依赖关系分析

  • SecurityConfig 依赖 JwtAuthenticationFilter、PermissionConfig、CorsConfig、SecurityExceptionHandlers、ResourceController(现需认证)
  • WebMvcConfig 依赖 ApiPermissionInterceptor,注册到/api/**路径
  • ApiPermissionInterceptor 依赖 ApiPermissionCache 和 AntPathMatcher
  • ApiPermissionCache 依赖 SysMenuMapper 和 Caffeine缓存
  • DataScopeInterceptor 依赖 DataScopeTables、DataScopeHelper、DataVisibilityContext、DataScopeLevel
  • JwtAuthenticationFilter 依赖 TokenService、PermissionResolver(新增)、SecurityContext
  • PermissionResolverImpl 依赖多个 Mapper 和缓存服务,实现完整的权限解析逻辑
  • ResourceController 依赖 IResourceService、FileApi,且需要 ADMIN 角色权限
  • 全局异常处理依赖 GlobalExceptionHandlerAdvice
classDiagram
class SecurityConfig {
+配置放行路径()
+配置鉴权规则()
+装配过滤器链()
}
class WebMvcConfig {
+注册API权限拦截器()
+配置/api/**路径()
}
class ApiPermissionInterceptor {
+URL模式匹配()
+权限码验证()
+fail-open策略()
}
class ApiPermissionCache {
+缓存权限规则()
+懒加载机制()
+主动失效()
}
class ApiPermissionRule {
+pattern : String
+perms : String
}
class JwtAuthenticationFilter {
+解析JWT()
+调用PermissionResolver()
+构建认证()
}
class PermissionResolver {
<<interface>>
+resolve(userId)
+visibleMenuTree(userId)
}
class PermissionResolverImpl {
+实现权限解析()
+处理数据可见性()
+计算权限码并集()
+归一化角色编码()
}
class PermissionGrant {
+封装授权信息()
+asAuthorities()
}
class DataScopeInterceptor {
+解析注解()
+构建SQL条件()
+注入查询()
}
class DataScopeTables {
+表字段映射()
}
class TokenService {
+生成令牌()
+校验令牌()
}
class PermissionConfig {
+权限映射()
}
class SecurityExceptionHandlers {
+处理安全异常()
}
class CorsConfig {
+配置跨域()
}
class GlobalExceptionHandlerAdvice {
+统一异常处理()
}
class ResourceController {
+listAll()
+saveOrUpdate()
+delete()
+uploadIcon()
+需要ADMIN角色权限()
}
class IResourceService {
+listAll()
+save()
+delete()
+uploadIcon()
}
class ResourceServiceImpl {
+实现资源服务逻辑()
+层级约束验证()
+字段必填校验()
+级联清理()
}
SecurityConfig --> JwtAuthenticationFilter : "装配"
SecurityConfig --> PermissionConfig : "读取"
SecurityConfig --> SecurityExceptionHandlers : "注册"
SecurityConfig --> CorsConfig : "集成"
SecurityConfig --> ResourceController : "受保护接口"
WebMvcConfig --> ApiPermissionInterceptor : "注册"
ApiPermissionInterceptor --> ApiPermissionCache : "依赖"
ApiPermissionCache --> ApiPermissionRule : "返回"
JwtAuthenticationFilter --> PermissionResolver : "依赖(新增)"
PermissionResolver <|.. PermissionResolverImpl : "实现"
PermissionResolverImpl --> PermissionGrant : "返回"
DataScopeInterceptor --> DataScopeTables : "读取映射"
DataScopeInterceptor --> TokenService : "间接依赖(用户上下文)"
JwtAuthenticationFilter --> TokenService : "使用"
ResourceController --> IResourceService : "依赖"
IResourceService --> ResourceServiceImpl : "实现"

图表来源

  • SecurityConfig.java
  • WebMvcConfig.java
  • ApiPermissionInterceptor.java
  • ApiPermissionCache.java
  • ApiPermissionRule.java
  • ResourceController.java
  • IResourceService.java
  • ResourceServiceImpl.java
  • JwtAuthenticationFilter.java
  • DataScopeInterceptor.java
  • DataScopeTables.java
  • TokenService.java
  • PermissionConfig.java
  • SecurityExceptionHandlers.java
  • CorsConfig.java
  • GlobalExceptionHandlerAdvice.java
  • PermissionResolver.java
  • PermissionResolverImpl.java
  • PermissionGrant.java

章节来源

  • SecurityConfig.java
  • WebMvcConfig.java
  • ApiPermissionInterceptor.java
  • ApiPermissionCache.java
  • ApiPermissionRule.java
  • ResourceController.java
  • DataScopeInterceptor.java
  • JwtAuthenticationFilter.java
  • PermissionResolver.java
  • PermissionResolverImpl.java
  • PermissionGrant.java

性能考虑

  • JWT 校验开销:建议缓存用户权限与角色信息,减少频繁查询
  • 数据权限 SQL 拼接:避免复杂子查询,优先使用索引字段(如 dept_id、user_id)
  • 拦截器粒度:仅在必要方法上使用 @DataScope,降低不必要的解析成本
  • 跨域预检:合理配置预检缓存,减少 OPTIONS 请求频率
  • 异常处理:统一异常处理避免重复日志与堆栈打印
  • 权限验证优化:通过严格的角色权限控制,提升系统安全性
  • API重构优化:标准化的动作后缀模式提高了API的一致性和可维护性
  • 权限解析优化:新的 PermissionResolver 采用单次查询链,避免多次数据库访问
  • fail-closed策略:权限解析失败直接拒绝请求,避免部分成功状态的性能浪费
  • API权限缓存优化:使用Caffeine缓存权限规则,避免频繁数据库查询
  • AntPathMatcher优化:预编译路径匹配器,提高URL匹配效率
  • 懒加载机制:权限规则按需加载,减少启动时间

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

故障排查指南

  • 认证失败
    • 检查请求头 Authorization 是否正确携带 Bearer 令牌
    • 确认 TokenService 的密钥与算法配置一致
    • 查看 SecurityExceptionHandlers 的错误码与消息
  • 授权拒绝
    • 核对 PermissionConfig 中的 URL 与权限标识
    • 确认用户角色与菜单权限是否匹配
    • 检查资源管理接口是否需要 ADMIN 角色权限
    • 检查 PermissionResolver 的权限解析逻辑是否正常
  • 数据权限不生效
    • 检查 @DataScope 注解参数是否与 DataScopeTables 映射一致
    • 验证 DataVisibilityContext 中用户上下文是否正确设置
    • 查看生成的 SQL 片段是否符合预期
  • 跨域问题
    • 检查 CorsConfig 的域名、方法与头部配置
    • 确认预检请求是否被放行
  • 资源管理接口访问问题
    • 确认用户是否具有 ADMIN 角色权限
    • 检查 JWT 令牌中是否包含正确的角色信息
    • 验证 SecurityConfig 中的放行路径配置
  • API端点调用问题
    • 确认使用的是新的标准化动作后缀模式
    • 检查POST请求的参数格式是否正确
    • 验证DELETE操作是否使用了POST /api/resources/delete
  • 权限解析问题
    • 检查 PermissionResolverImpl 的数据库查询是否正常
    • 确认用户角色、菜单权限配置是否正确
    • 验证 DataVisibilityContext 的加载和清理逻辑
  • API权限拦截问题
    • 检查ApiPermissionCache是否正确加载权限规则
    • 确认SysMenu表中button类型的apiUrl配置是否正确
    • 验证用户权限集合是否包含所需的perms
    • 检查AntPathMatcher的路径匹配是否符合预期

章节来源

  • SecurityExceptionHandlers.java
  • GlobalExceptionHandlerAdvice.java
  • DataScopeInterceptor.java
  • DataScopeTables.java
  • CorsConfig.java
  • JwtAuthenticationFilter.java
  • SecurityConfig.java
  • ResourceController.java
  • PermissionResolverImpl.java
  • ApiPermissionInterceptor.java
  • ApiPermissionCache.java

结论

本项目的安全与数据权限体系以 Spring Security 为核心,结合 JWT 无状态认证与注解驱动的数据权限拦截器,实现了灵活且可扩展的安全控制。通过统一的异常处理与跨域配置,保障了前后端分离场景下的稳定交互。最新的架构更新引入了统一的权限解析引擎(PermissionResolver)和API权限拦截器架构,JwtAuthenticationFilter经过重大简化,现在通过单一的 permissionResolver.resolve() 方法处理认证上下文加载和Spring Security权限创建,采用 fail-closed 策略确保安全性。建议在新增接口时遵循以下最佳实践:

  • 明确接口是否需要鉴权与数据权限
  • 正确配置 @DataScope 与表映射
  • 完善权限配置与白名单(谨慎使用)
  • 使用统一异常处理与返回格式
  • 对敏感接口实施严格的角色权限控制
  • 遵循标准化的动作后缀API模式
  • 利用 PermissionResolver 进行统一的权限解析
  • 为需要细粒度权限控制的接口配置API权限规则

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

附录

  • 配置文件参考
    • application.yml(应用配置)
  • 常用注解与工具
    • @DataScope、@DataOwnership
    • DataScopeHelper、DataVisibilityContext、SecurityUtils
  • 已更新的资源管理接口
    • GET /api/resources/list:获取全量资源树
    • POST /api/resources/saveOrUpdate:新增或编辑节点
    • POST /api/resources/delete:删除节点(表单参数)
    • POST /api/resources/icon/upload:图标上传
    • 所有接口现在都需要 ADMIN 角色权限
    • 主要用于权限结构的初始化和维护,但需要完整认证
  • 新增的权限解析组件
    • PermissionResolver:权限解析接口
    • PermissionResolverImpl:权限解析实现
    • PermissionGrant:权限授予对象
    • 支持 fail-closed 策略和完整的授权信息查询
  • 新增的API权限拦截器组件
    • WebMvcConfig:MVC配置,注册API权限拦截器
    • ApiPermissionInterceptor:动态权限验证拦截器
    • ApiPermissionCache:API权限规则缓存
    • ApiPermissionRule:权限规则记录类
    • 支持Ant风格路径匹配和fail-open策略

章节来源

  • application.yml
  • application.yml
  • DataScope.java
  • DataOwnership.java
  • DataScopeHelper.java
  • DataVisibilityContext.java
  • SecurityUtils.java
  • ResourceController.java
  • SecurityConfig.java
  • WebMvcConfig.java
  • ApiPermissionInterceptor.java
  • ApiPermissionCache.java
  • ApiPermissionRule.java
  • PermissionResolver.java
  • PermissionResolverImpl.java
  • PermissionGrant.java