Files
springboot-template/DETAILS.md
shenjianZ 40c85c3c1f feat: 实现完整的 RBAC 权限管理系统与基础设施增强
在初始认证基础上,新增完整的 RBAC 权限模型(角色、权限、菜单三级管理),
  集成审计日志、接口限流、登录失败锁定、Refresh Token 机制、Redis 分布式缓存与锁、
  RocketMQ 消息队列,并引入 Flyway 数据库版本管理,同时补充项目文档与使用示例
2026-04-10 10:58:22 +08:00

726 lines
35 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
📋 项目概览
这是一个企业级 Spring Boot 3.x 模板项目,提供了完整的用户认证与权限管理系统。
核心功能
┌─────────────────────────────────────────────────────────────┐
│ 核心功能模块 │
├─────────────────────────────────────────────────────────────┤
│ 1. 用户认证 JWT + Refresh Token 双Token机制 │
│ 2. 权限管理 RBAC角色-权限)模型 │
│ 3. 账户安全 登录失败锁定、密码重置、限流 │
│ 4. 审计日志 记录所有敏感操作 │
│ 5. 缓存支持 Redis 缓存、分布式锁 │
│ 6. 消息队列 RocketMQ 异步处理 │
└─────────────────────────────────────────────────────────────┘
技术栈
Searched for 1 pattern, read 1 file (ctrl+o to expand)
● 现在让我为你详细剖析整个项目:
---
一、项目技术栈
┌─────────────────┬────────┬────────────────┐
│ 技术 │ 版本 │ 用途 │
├─────────────────┼────────┼────────────────┤
│ Spring Boot │ 3.5.6 │ 基础框架 │
├─────────────────┼────────┼────────────────┤
│ Spring Security │ 6.x │ 认证授权 │
├─────────────────┼────────┼────────────────┤
│ Spring Data JPA │ - │ ORM 数据访问 │
├─────────────────┼────────┼────────────────┤
│ MySQL │ - │ 关系数据库 │
├─────────────────┼────────┼────────────────┤
│ Redis │ - │ 缓存/分布式锁 │
├─────────────────┼────────┼────────────────┤
│ RocketMQ │ 2.3.1 │ 消息队列 │
├─────────────────┼────────┼────────────────┤
│ JJWT │ 0.11.5 │ JWT Token │
├─────────────────┼────────┼────────────────┤
│ Flyway │ - │ 数据库版本管理 │
├─────────────────┼────────┼────────────────┤
│ Lombok │ - │ 简化代码 │
└─────────────────┴────────┴────────────────┘
---
二、项目目录结构
● Bash(tree -L 4 -I 'target|.git' D:\tmp\springboot-template\src\main\java\com\aisi\template 2>/dev/null || find
D:\tmp\springboot-template\src\main\java\com\aisi\temp…)
 find: D:tmpspringboot-templatesrcmainjavacomaisitemplate: No such file or directory
sed: -e expression #1, char 7: unterminated `s' command
Searched for 1 pattern (ctrl+o to expand)
● 项目分层架构
├── 📁 annotation/ # 自定义注解AOP切点
│ ├── @AuditLog # 审计日志注解
│ ├── @RateLimit # 限流注解
│ └── @StrongPassword # 强密码校验注解
├── 📁 aspect/ # AOP切面
│ ├── AuditLogAspect # 审计日志切面
│ └── RateLimitAspect # 限流切面
├── 📁 config/ # 配置类
│ ├── SecurityConfig # Spring Security 安全配置
│ ├── RedisConfig # Redis 配置
│ ├── JpaConfig # JPA 审计配置
│ ├── WebConfig # Web MVC 配置
│ ├── JacksonConfig # JSON 序列化配置
│ └── OpenApiConfig # Swagger 文档配置
├── 📁 constants/ # 常量定义
│ ├── AppConstants # 应用常量
│ └── SecurityConstants # 安全常量
├── 📁 controller/ # 控制层API接口
│ ├── UserController # 用户接口
│ ├── RoleController # 角色接口
│ ├── MenuController # 菜单接口
│ └── PermissionController # 权限接口
├── 📁 domain/ # 领域模型
│ ├── entity/ # 实体类(数据库表)
│ ├── dto/ # 数据传输对象(请求参数)
│ ├── vo/ # 视图对象(响应数据)
│ └── enums/ # 枚举类
├── 📁 service/ # 服务层(业务逻辑)
│ └── impl/ # 服务实现
├── 📁 repository/ # 数据访问层DAO
├── 📁 filter/ # 过滤器
│ └── JwtAuthenticationFilter # JWT 认证过滤器
├── 📁 handler/ # 处理器
│ └── GlobalExceptionHandler # 全局异常处理
├── 📁 interceptor/ # 拦截器
│ └── LoggingInterceptor # 日志拦截器
├── 📁 mq/ # 消息队列
│ ├── producer/ # 消息生产者
│ ├── consumer/ # 消息消费者
│ └── message/ # 消息定义
├── 📁 utils/ # 工具类
│ ├── JwtUtil # JWT 工具
│ ├── SecurityUtils # 安全工具
│ ├── RedisCache # Redis 缓存
│ └── RedisLock # 分布式锁
├── 📁 examples/ # 使用示例
│ ├── RedisUsageExample # Redis 使用示例
│ └── TransactionExample # 事务使用示例
└── 📁 exception/ # 异常类
├── BusinessException # 业务异常
└── RateLimitExceededException # 限流异常
---
三、核心架构设计
3.1 认证架构
┌─────────────────────────────────────────────────────────────────┐
│ 认证流程 │
└─────────────────────────────────────────────────────────────────┘
客户端 Spring Boot JWT Token
│ │ │
│ 1. POST /api/v1/user/login │ │
│ {username, password} │ │
│ ────────────────────────────>│ │
│ │ │
│ │ 2. 验证用户名密码 │
│ │ 3. 检查账户锁定状态 │
│ │ 4. 生成 Access Token(1h) │
│ │ 5. 生成 Refresh Token(7d) │
│ │ 6. 存储 Refresh Token │
│ │ │
│ 7. 返回 Token │ │
│ {accessToken, │ │
│ refreshToken} │ │
│ <────────────────────────────│ │
│ │ │
│ 8. 后续请求携带 Token │ │
│ Authorization: Bearer │ │
│ {accessToken} │ │
│ ────────────────────────────>│ │
│ │ │
│ │ 9. JwtAuthenticationFilter │
│ │ 解析 Token │
│ │ 验证签名 │
│ │ 检查黑名单 │
│ │ 设置认证上下文 │
│ │ │
│ 10. 返回业务数据 │ │
│ <────────────────────────────│ │
3.2 权限模型RBAC
┌─────────────────────────────────────────────────────────────────┐
│ RBAC 权限模型 │
└─────────────────────────────────────────────────────────────────┘
用户(User) ──多对多── 角色(Role) ──多对多── 权限(Permission)
│ │ │
│ │ │
having having having
accounts roles permissions
示例:
用户 alice ──拥有──> [ROLE_USER, ROLE_ADMIN]
└── ROLE_ADMIN ──拥有──> [user:read, user:write,
role:read, menu:read]
权限计算:
alice 的权限 = ROLE_USER的权限 ROLE_ADMIN的权限
使用 @PreAuthorize 注解控制访问:
@PreAuthorize("hasAuthority('user:write')")
public void updateUser() { ... }
3.3 安全防护机制
┌─────────────────────────────────────────────────────────────────┐
│ 安全防护体系 │
└─────────────────────────────────────────────────────────────────┘
防护类型 实现方式 阈值
─────────────────────────────────────────────────────────────────
登录失败锁定 Redis计数器 + 时间窗口 5次/30分钟
密码重置限流 Redis计数器 + 冷却时间 1次/60秒
API接口限流 Redis + @RateLimit切面 可配置
密码强度校验 @StrongPassword注解 大小写+数字+特殊字符
Token黑名单 Redis + JTI 登出时加入
Token轮换 Refresh Token机制 刷新后旧Token失效
密码重置 邮箱验证码 6位/10分钟有效
---
四、数据库设计
Searched for 1 pattern, read 2 files (ctrl+o to expand)
● 数据库表结构
┌─────────────────────────────────────────────────────────────────┐
│ 数据库表关系图 │
└─────────────────────────────────────────────────────────────────┘
核心表关系:
users (用户表)
├── 1:N ──> refresh_tokens (刷新令牌表)
├── N:M ──> sys_role (角色表) ── N:M ──> sys_permission (权限表)
│ │ │
│ └── N:M ──> sys_menu (菜单表) │
│ │
└── 1:N ──> password_reset_codes (密码重置码表)
辅助表:
├── sys_audit_log (审计日志表)
└── sys_user_role (用户-角色关联表)
sys_role_permission (角色-权限关联表)
sys_role_menu (角色-菜单关联表)
┌────────────────┬──────────┬─────────────────────────────────────────────────────────────────────┐
│ 表名 │ 用途 │ 关键字段 │
├────────────────┼──────────┼─────────────────────────────────────────────────────────────────────┤
│ users │ 用户信息 │ username, password, email, status, failed_login_count, locked_until │
├────────────────┼──────────┼─────────────────────────────────────────────────────────────────────┤
│ sys_role │ 角色定义 │ role_code(ROLE_ADMIN等), role_name, status │
├────────────────┼──────────┼─────────────────────────────────────────────────────────────────────┤
│ sys_permission │ 权限定义 │ permission_code(user:read等), resource, action │
├────────────────┼──────────┼─────────────────────────────────────────────────────────────────────┤
│ sys_menu │ 菜单定义 │ menu_name, menu_type(目录/页面/按钮), parent_id │
├────────────────┼──────────┼─────────────────────────────────────────────────────────────────────┤
│ refresh_tokens │ 刷新令牌 │ token_hash(SHA-256), expires_at, revoked │
├────────────────┼──────────┼─────────────────────────────────────────────────────────────────────┤
│ sys_audit_log │ 审计日志 │ user_id, action(LOGIN/CREATE等), resource, status │
└────────────────┴──────────┴─────────────────────────────────────────────────────────────────────┘
---
五、核心模块详解
5.1 认证模块
核心类关系:
SecurityConfig (配置入口)
├── CustomUserDetailsService (加载用户)
│ └── UserRepository (查询用户)
├── JwtAuthenticationFilter (JWT过滤器)
│ ├── JwtUtil (Token生成/解析)
│ └── TokenService (Token管理)
│ └── RefreshTokenRepository
└── PasswordEncoder (BCrypt加密)
认证流程详解:
Read 1 file (ctrl+o to expand)
● JWT认证过滤器详解
Read 1 file (ctrl+o to expand)
● 认证流程图
┌─────────────────────────────────────────────────────────────────────────┐
│ 完整认证流程 │
└─────────────────────────────────────────────────────────────────────────┘
1. 用户登录
├─> UserController.login()
│ │
│ ├─> UserService.login()
│ │ │
│ │ ├─> 1. 校验用户名密码
│ │ ├─> 2. 检查账户锁定状态
│ │ ├─> 3. 检查账户启用状态
│ │ ├─> 4. 记录登录失败(成功则清除)
│ │ ├─> 5. 生成 Access Token (1小时)
│ │ ├─> 6. 生成 Refresh Token (7天)
│ │ ├─> 7. 存储 Refresh Token 到数据库
│ │ ├─> 8. 发送登录消息到 MQ
│ │ └─> 9. 返回 LoginResponseVo
│ │
│ └─> 返回 { accessToken, refreshToken, expiresIn, userInfo }
2. 后续请求
├─> JwtAuthenticationFilter.doFilterInternal()
│ │
│ ├─> 1. 提取 Token (Authorization: Bearer {token})
│ ├─> 2. 验证 Token 签名
│ ├─> 3. 检查黑名单 (登出时加入)
│ ├─> 4. 检查过期时间
│ ├─> 5. 加载用户详情
│ └─> 6. 设置认证到 SecurityContext
└─> 继续处理请求
3. Token 刷新
├─> UserController.refreshToken()
│ │
│ └─> TokenService.refreshToken()
│ │
│ ├─> 1. 验证 Refresh Token
│ ├─> 2. 撤销旧 Refresh Token
│ ├─> 3. 生成新的 Access Token
│ ├─> 4. 生成新的 Refresh Token
│ └─> 5. 返回新 Token
4. 用户登出
├─> UserController.logout()
│ │
│ └─> TokenService.addTokenToBlacklist()
│ │
│ ├─> 1. 提取 Token 的 JTI
│ ├─> 2. 计算剩余过期时间
│ ├─> 3. 存入 Redis 黑名单
│ └─> 4. 撤销所有 Refresh Token
5.2 权限模块详解
Read 1 file (ctrl+o to expand)
● 权限加载流程
┌─────────────────────────────────────────────────────────────────────────┐
│ 权限加载与验证流程 │
└─────────────────────────────────────────────────────────────────────────┘
1. 用户登录时加载权限
├─> CustomUserDetailsService.loadUserByUsername(username)
│ │
│ ├─> 查询用户: User + Roles (JOIN FETCH)
│ │
│ ├─> 遍历用户的每个角色
│ │ │
│ │ └─> 角色 ROLE_ADMIN
│ │ │
│ │ ├─> 添加角色权限: "ROLE_ADMIN"
│ │ │
│ │ └─> 添加角色下的具体权限
│ │ ├── "user:create"
│ │ ├── "user:read"
│ │ ├── "user:update"
│ │ ├── "role:read"
│ │ └── ...
│ │
│ └─> 合并所有角色的权限 → Set<GrantedAuthority>
2. 接口权限验证
├─> @PreAuthorize("hasAuthority('user:create')")
│ │
│ └─> Spring Security 检查当前用户的权限列表
│ │
│ └─> 包含 "user:create" → ✅ 允许访问
│ 不包含 → ❌ 拒绝访问
3. 权限类型说明
├── 角色权限 (ROLE_XXX)
│ ├── 用于粗粒度控制:判断用户角色
│ └── 使用方式: @PreAuthorize("hasRole('ADMIN')")
│ 等价于: hasAuthority('ROLE_ADMIN')
└── 具体权限 (XXX:YYY)
├── 用于细粒度控制:具体操作
└── 使用方式: @PreAuthorize("hasAuthority('user:create')")
5.3 安全防护模块
Read 1 file (ctrl+o to expand)
● 安全防护机制详解
┌─────────────────────────────────────────────────────────────────────────┐
│ 安全防护机制 │
└─────────────────────────────────────────────────────────────────────────┘
1. 登录失败锁定机制
├─> 触发条件:连续登录失败 5 次(可配置)
├─> 锁定时长30 分钟(可配置)
├─> 实现方式:
│ ├── users 表存储失败次数和锁定时间
│ ├── failed_login_count失败次数
│ └── locked_until锁定到期时间
└─> 自动解锁:锁定时间到期后自动解锁
2. 限流机制 (@RateLimit)
├─> 支持的限流类型:
│ ├── IP按 IP 地址限流
│ ├── USER按用户 ID 限流
│ └── GLOBAL全局限流
├─> 使用方式:
@RateLimit(permitted = 10, seconds = 60, limitType = LimitType.USER)
│ public void sensitiveOperation() { ... }
└─> 实现原理:
├── Redis 存储计数器
├── 格式rate_limit:user:{userId}
├── 过期时间:时间窗口
└── 超过限制:抛出 RateLimitExceededException
3. 密码重置机制
├─> 验证码规则:
│ ├── 6 位随机数字
│ ├── 10 分钟有效期
│ ├── 最多尝试 5 次
│ └── 60 秒请求冷却时间
├─> 防用户名枚举:
│ └── 无论邮箱是否存在,都返回相同消息
└─> 验证码存储:
├── 哈希存储SHA-256
└── 数据库 + 状态管理
4. Token 黑名单机制
├─> 触发场景:
│ ├── 用户主动登出
│ ├── 管理员强制下线
│ └── 修改密码后
├─> 存储方式Redis
└─> 键格式token:blacklist:{jti}
└── 过期时间Token 剩余有效期
5.4 审计日志模块
Read 1 file (ctrl+o to expand)
● 审计日志使用示例
// 在方法上添加 @AuditLog 注解
@AuditLog(
action = "CREATE",
resource = "user",
description = "创建用户 {0}"
)
public void createUser(String username) {
// 业务逻辑
}
// AOP 切面会自动记录:
// - 操作用户(从 SecurityContext 获取)
// - 操作类型CREATE
// - 资源类型user
// - 操作描述:"创建用户 alice"
// - 请求信息IP、User-Agent
// - 操作结果:成功/失败
5.5 Redis 缓存模块
Read 1 file (ctrl+o to expand)
● Redis 缓存使用场景
┌─────────────────────────────────────────────────────────────────────────┐
│ Redis 使用场景总结 │
└─────────────────────────────────────────────────────────────────────────┘
1. Token 黑名单
├── 键格式token:blacklist:{jti}
├── 值1固定值只判断键是否存在
└── 过期时间Token 剩余有效期
2. Refresh Token 存储
├── 键格式refresh_token:{tokenHash}
├── 值用户ID
└── 过期时间7 天
3. 限流计数器
├── 键格式rate_limit:{type}:{identifier}
│ ├── type: ip / user / global
│ └── identifier: IP地址 / 用户ID
├── 值:当前请求次数
└── 过期时间:时间窗口
4. 登录失败计数
├── 键格式login_attempts:{username}
├── 值:失败次数
└── 过期时间锁定时长30分钟
5. 分布式锁
├── 键格式lock:{resource}:{id}
├── 值唯一标识UUID
├── 过期时间:锁超时时间(防止死锁)
└── 实现方式SET NX EX + Lua 脚本
6. 用户会话缓存
├── 键格式session:user:{userId}
├── 值会话信息登录IP、时间等
└── 过期时间24 小时
7. 密码重置验证码
├── 存储:数据库 password_reset_codes 表
└── 限制Redis + 冷却时间
5.6 消息队列模块
Read 3 files (ctrl+o to expand)
● RocketMQ 消息队列架构
┌─────────────────────────────────────────────────────────────────────────┐
│ RocketMQ 消息流程 │
└─────────────────────────────────────────────────────────────────────────┘
用户登录
├─> UserService.login()
│ │
│ ├─> 1. 验证用户
│ ├─> 2. 生成 Token
│ ├─> 3. 发送登录消息到 MQ
│ │ │
│ │ └─> UserMessageProducer.sendLoginMessage()
│ │ │
│ │ └─> rocketMQTemplate.asyncSend(user-topic, message)
│ │
│ └─> 4. 返回响应(不等待 MQ 处理)
└─> RocketMQ: user-topic
└─> UserMessageConsumer.onMessage()
├─> 1. 收到消息
├─> 2. 根据 messageType 路由
│ │
│ ├── REGISTER → handleRegisterMessage()
│ │ └─> 发送欢迎邮件、初始化数据
│ │
│ ├── LOGIN → handleLoginMessage()
│ │ └─> 记录登录日志、更新最后登录时间
│ │
│ ├── LOGOUT → handleLogoutMessage()
│ │ └─> 清理缓存、登出其他设备
│ │
│ ├── UPDATE → handleUpdateMessage()
│ │ └─> 同步数据到数据仓库、清除缓存
│ │
│ └── DELETE → handleDeleteMessage()
│ └─> 清理关联数据、归档
└─> 3. 处理完成,确认消费
---
六、配置文件解析
Searched for 1 pattern, read 2 files (ctrl+o to expand)
● 配置文件结构总结
┌─────────────────────────────────────────────────────────────────────────┐
│ 配置文件结构 │
└─────────────────────────────────────────────────────────────────────────┘
application.yaml (主配置)
├── spring.profiles.active: dev (激活环境)
├── server.port: 8080
└── 支持环境变量覆盖 (.env 文件)
application-dev.yaml (开发环境)
├── 数据库配置 (MySQL)
│ ├── url: jdbc:mysql://localhost:3306/template
│ ├── username: root
│ └── password: root
├── JPA 配置
│ ├── ddl-auto: validate (不自动建表,由 Flyway 管理)
│ └── show-sql: false
├── Flyway (数据库版本管理)
│ ├── enabled: true
│ └── locations: classpath:db/migration
├── Redis 配置
│ ├── host: localhost:6379
│ └── database: 0
├── 邮件配置 (SMTP)
│ ├── host: smtp.163.com
│ └── port: 465
├── JWT 配置
│ ├── secret: 密钥HS512 需要 64 字符)
│ ├── access-token-expiration: 3600 秒 (1 小时)
│ └── refresh-token-expiration: 604800 秒 (7 天)
├── 业务配置
│ ├── 登录失败锁定: 5 次 / 30 分钟
│ └── 密码重置: 6 位验证码 / 10 分钟有效
└── RocketMQ 配置
└── name-server: localhost:9876
---
七、请求处理完整流程
┌─────────────────────────────────────────────────────────────────────────┐
│ 完整请求处理流程 │
└─────────────────────────────────────────────────────────────────────────┘
1. 客户端发起请求
├─> GET /api/v1/user/info
│ Headers:
│ - Authorization: Bearer {accessToken}
│ - Content-Type: application/json
2. 进入 Spring MVC 处理链
├─> LoggingInterceptor (拦截器)
│ ├── 记录请求开始时间
│ ├── 生成请求 ID (8 位 UUID)
│ ├── 获取当前用户信息
│ └── 记录请求开始日志
3. 进入 Filter 链
├─> JwtAuthenticationFilter (JWT 过滤器)
│ ├── 提取 Token: Bearer {token}
│ ├── 验证 Token 签名 (HS512)
│ ├── 检查黑名单 (Redis: token:blacklist:{jti})
│ ├── 检查过期时间
│ ├── 加载用户详情
│ └── 设置认证到 SecurityContext
4. 权限验证
├─> @PreAuthorize("hasAuthority('user:read')")
│ └── 检查用户权限列表是否包含 "user:read"
5. AOP 切面处理
├─> AuditLogAspect (审计日志切面)
│ ├── 检查 @AuditLog 注解
│ ├── 提取请求信息
│ ├── 提取当前用户信息
│ └── 准备记录审计日志(异步执行)
6. 执行 Controller
├─> UserController.getUserInfo()
│ ├── 从 SecurityContext 获取用户
│ └── 返回用户信息 (UserVo)
7. 响应处理
├─> 全局异常处理
│ └── GlobalExceptionHandler
│ ├── 捕获业务异常
│ ├── 捕获参数校验异常
│ └── 捕获系统异常
8. 后置处理
├─> LoggingInterceptor.afterCompletion()
│ ├── 计算请求耗时
│ └── 记录请求完成日志
└─> 返回响应
└─> RestBean<UserVo>
├── code: 200
├── message: "操作成功"
└── data: UserVo
---
八、总结与建议
项目优势
1. 架构清晰:分层明确,职责单一
2. 安全完善JWT + RBAC + 多重防护
3. 扩展性强:模块化设计,易于扩展
4. 文档完整:全中文注释,便于维护
5. 异步解耦RocketMQ 消息队列
适用场景
- 企业内部管理系统
- SaaS 多租户平台
- 需要 RBAC 权限的系统
- 需要审计日志的系统
- 需要高安全性的系统
扩展建议
1. 数据权限:在 RBAC 基础上增加数据权限控制
2. 多租户:添加租户隔离机制
3. OAuth2支持第三方登录微信、GitHub等
4. 监控告警:集成 Prometheus + Grafana
5. 日志收集:集成 ELKElasticsearch + Logstash + Kibana