feat: 实现完整的 RBAC 权限管理系统与基础设施增强
在初始认证基础上,新增完整的 RBAC 权限模型(角色、权限、菜单三级管理), 集成审计日志、接口限流、登录失败锁定、Refresh Token 机制、Redis 分布式缓存与锁、 RocketMQ 消息队列,并引入 Flyway 数据库版本管理,同时补充项目文档与使用示例
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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. 禁用 CSRF(JWT 不需要)
|
||||
.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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user