feat: 实现完整的 RBAC 权限管理系统与基础设施增强

在初始认证基础上,新增完整的 RBAC 权限模型(角色、权限、菜单三级管理),
  集成审计日志、接口限流、登录失败锁定、Refresh Token 机制、Redis 分布式缓存与锁、
  RocketMQ 消息队列,并引入 Flyway 数据库版本管理,同时补充项目文档与使用示例
This commit is contained in:
2026-04-10 10:58:22 +08:00
parent 3a9bf61839
commit 40c85c3c1f
97 changed files with 13434 additions and 351 deletions

View File

@@ -10,25 +10,47 @@ import org.springframework.context.annotation.Configuration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* Jackson 配置类
* 配置 JSON 序列化相关设置
*
* 主要功能:
* 1. 日期时间格式化:统一日期时间格式
* 2. 禁用时间戳:使用可读的日期字符串
*
* @author Claude
* @since 2024-04-09
*/
@Configuration
public class JacksonConfig {
/**
* 配置 ObjectMapper
* 步骤:
* 1. 创建 ObjectMapper 对象
* 2. 注册 JavaTimeModule支持 Java 8 日期时间类型)
* 3. 配置 LocalDateTime 序列化格式
* 4. 禁用时间戳格式
*
* @return ObjectMapper 对象
*/
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
// 配置日期时间格式
// 1. 配置日期时间模块
JavaTimeModule javaTimeModule = new JavaTimeModule();
// 定义日期时间格式
// 2. 定义日期时间格式yyyy-MM-dd HH:mm:ss
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
// 3. 注册日期时间模块
mapper.registerModule(javaTimeModule);
// 禁用时间戳格式
// 4. 禁用时间戳格式(使用可读的日期字符串)
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return mapper;
}
}
}

View File

@@ -5,6 +5,19 @@ import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
/**
* JPA 配置类
* 配置 JPA 审计功能
*
* 主要功能:
* 1. 自动填充创建时间:@CreatedDate
* 2. 自动填充更新时间:@LastModifiedDate
*
* 使用说明:
* - 在实体类上添加 @EntityListeners(AuditingEntityListener.class)
* - 在字段上使用 @CreatedDate 和 @LastModifiedDate 注解
* - JPA 会自动维护这些字段的值
*
* @author Claude
* @since 2024-04-09
*/
@Configuration
@EnableJpaAuditing

View File

@@ -2,14 +2,49 @@ package com.aisi.template.config;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.servers.Server;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
/**
* OpenAPI (Swagger) 配置类
* 配置 API 文档的安全认证
*
* 主要功能:
* 1. 配置 JWT Bearer 认证
* 2. 在 Swagger UI 中支持 JWT Token 测试
*
* 使用说明:
* 1. 访问 http://localhost:8080/swagger-ui.html
* 2. 点击右上角 "Authorize" 按钮
* 3. 输入 JWT Token格式Bearer {token}
* 4. 点击 "Authorize" 完成认证
*
* @author Claude
* @since 2024-04-09
*/
@Configuration
@SecurityScheme(
// 安全方案名称
name = "Bearer Authentication",
// 安全方案类型HTTP
type = SecuritySchemeType.HTTP,
// Bearer 格式JWT
bearerFormat = "JWT",
// 认证方案bearer
scheme = "bearer"
)
public class OpenApiConfig {
@Bean
public OpenAPI customOpenAPI(@Value("${app.openapi.server-url:http://localhost:8080}") String serverUrl) {
return new OpenAPI()
.servers(List.of(new Server()
.url(serverUrl)
.description("Default server")));
}
}

View File

@@ -13,14 +13,45 @@ import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* Redis 配置类
* 配置 Redis 序列化方式
*
* 主要功能:
* 1. RedisTemplate用于操作对象类型数据
* 2. StringRedisTemplate用于操作字符串类型数据
*
* 序列化配置:
* - Key使用 String 序列化
* - Value使用 JSON 序列化(支持类型信息)
* - HashKey使用 String 序列化
* - HashValue使用 JSON 序列化
*
* @author Claude
* @since 2024-04-09
*/
@Configuration
public class RedisConfig {
/**
* 配置 RedisTemplate用于操作对象
* 步骤:
* 1. 创建 RedisTemplate 对象
* 2. 配置 ObjectMapper支持类型信息
* 3. 配置 Key 序列化方式
* 4. 配置 Value 序列化方式
*
* @param factory Redis 连接工厂
* @param objectMapper Jackson ObjectMapper
* @return RedisTemplate 对象
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory, ObjectMapper objectMapper) {
// 1. 创建 RedisTemplate 对象
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 2. 配置 ObjectMapper支持类型信息用于反序列化时确定类型
ObjectMapper redisMapper = objectMapper.copy();
redisMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
redisMapper.activateDefaultTyping(
@@ -29,18 +60,35 @@ public class RedisConfig {
JsonTypeInfo.As.PROPERTY
);
// 3. 配置序列化器
StringRedisSerializer stringSerializer = new StringRedisSerializer();
GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer(redisMapper);
// 3.1 Key 使用 String 序列化
template.setKeySerializer(stringSerializer);
// 3.2 HashKey 使用 String 序列化
template.setHashKeySerializer(stringSerializer);
// 3.3 Value 使用 JSON 序列化
template.setValueSerializer(jsonSerializer);
// 3.4 HashValue 使用 JSON 序列化
template.setHashValueSerializer(jsonSerializer);
// 4. 执行初始化
template.afterPropertiesSet();
return template;
}
/**
* 配置 StringRedisTemplate用于操作字符串
* 说明:
* - StringRedisTemplate 专门用于处理字符串类型数据
* - Key 和 Value 都使用 String 序列化
* - 适用于简单的键值对操作
*
* @param factory Redis 连接工厂
* @return StringRedisTemplate 对象
*/
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
return new StringRedisTemplate(factory);

View File

@@ -2,6 +2,7 @@ package com.aisi.template.config;
import com.aisi.template.filter.JwtAuthenticationFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
@@ -19,46 +20,128 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
import java.util.List;
/**
* Spring Security 配置类
* 配置安全认证和授权相关设置
*
* 主要功能:
* 1. JWT 认证:配置 JWT 过滤器
* 2. CORS 配置:跨域资源共享配置
* 3. 会话管理无状态会话JWT
* 4. 授权规则:配置哪些请求需要认证
* 5. 密码编码:配置 BCrypt 密码编码器
*
* @author Claude
* @since 2024-04-09
*/
@Configuration
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {
/**
* JWT 认证过滤器
* 用于拦截请求并验证 JWT Token
*/
private final JwtAuthenticationFilter jwtAuthenticationFilter;
/**
* 允许的跨域来源
* 从配置文件读取默认http://localhost:5173, http://localhost:3000
*/
@Value("${app.cors.allowed-origins:http://localhost:5173,http://localhost:3000}")
private List<String> allowedOrigins;
/**
* 配置安全过滤器链
* 步骤:
* 1. 禁用 CSRF使用 JWT 不需要 CSRF 保护)
* 2. 配置 CORS
* 3. 设置会话管理为无状态JWT
* 4. 配置授权规则
* 5. 添加 JWT 认证过滤器
*
* @param http HttpSecurity 对象
* @return 安全过滤器链
*/
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// 1. 禁用 CSRFJWT 不需要)
.csrf(AbstractHttpConfigurer::disable)
// 2. 配置 CORS
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
// 3. 设置会话管理为无状态
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
// 4. 配置授权规则
.authorizeHttpRequests(auth -> auth
.requestMatchers("/v3/api-docs/**","/swagger-ui/**", "/swagger-ui.html").permitAll()
.requestMatchers("/api/v1/user/register", "/api/v1/user/login").permitAll()
// 4.1 Swagger 文档:允许匿名访问
.requestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll()
// 4.2 用户注册、登录和刷新令牌:允许匿名访问
.requestMatchers("/api/v1/user/register", "/api/v1/user/login", "/api/v1/user/refresh").permitAll()
// 4.3 密码重置:允许匿名访问
.requestMatchers("/api/v1/user/password-reset/**").permitAll()
// 4.4 获取当前用户信息:需要认证
.requestMatchers("/api/v1/user/info").authenticated()
// 4.5 其他所有请求:需要认证
.anyRequest().authenticated()
)
// 5. 添加 JWT 认证过滤器(在用户名密码过滤器之前)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
/**
* 配置 CORS跨域资源共享
* 步骤:
* 1. 创建 CORS 配置
* 2. 设置允许的来源
* 3. 设置允许的 HTTP 方法
* 4. 设置允许的请求头
* 5. 设置暴露的响应头
* 6. 允许携带凭证Cookie
* 7. 设置预检请求缓存时间
*
* @return CORS 配置源
*/
@Bean
public CorsConfigurationSource corsConfigurationSource() {
// 1. 创建 CORS 配置
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOriginPatterns(List.of("*"));
configuration.setAllowedMethods(List.of("*"));
configuration.setAllowedHeaders(List.of("*"));
// 2. 设置允许的来源
configuration.setAllowedOrigins(allowedOrigins);
// 3. 设置允许的 HTTP 方法
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
// 4. 设置允许的请求头
configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type", "Accept", "Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"));
// 5. 设置暴露的响应头
configuration.setExposedHeaders(Arrays.asList("Authorization", "Content-Type"));
// 6. 允许携带凭证Cookie
configuration.setAllowCredentials(true);
configuration.setExposedHeaders(List.of("*"));
// 7. 设置预检请求缓存时间1 小时)
configuration.setMaxAge(3600L);
// 8. 注册 CORS 配置
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
/**
* 配置密码编码器
* 说明:
* - 使用 BCrypt 算法对密码进行加密
* - 每次加密都会生成不同的哈希值(自带盐值)
* - 强度因子默认为 10
*
* @return BCrypt 密码编码器
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();

View File

@@ -6,17 +6,41 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Web MVC 配置类
* 配置拦截器和其他 Web 相关设置
*
* 主要功能:
* 1. 拦截器配置:注册日志拦截器
*
* @author Claude
* @since 2024-04-09
*/
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
/**
* 日志拦截器
* 用于记录请求和响应信息
*/
private final LoggingInterceptor loggingInterceptor;
/**
* 配置拦截器
* 步骤:
* 1. 注册日志拦截器
* 2. 拦截所有请求(/**
* 3. 可配置排除路径
*
* @param registry 拦截器注册表
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loggingInterceptor)
// 1. 拦截所有请求
.addPathPatterns("/**")
// 2. 排除路径(可在此添加需要排除的路径)
.excludePathPatterns();
}
}