更新 src/main/java/com/vibevault/config/SecurityConfig.java
Some checks are pending
autograde-final-vibevault / check-trigger (push) Waiting to run
autograde-final-vibevault / grade (push) Blocked by required conditions

This commit is contained in:
张雪尔 2025-12-22 04:05:26 +08:00
parent d6fb6fac4c
commit 16896dee2c

View File

@ -1,15 +1,16 @@
package com.vibevault.config; package com.vibevault.config;
import com.vibevault.security.JwtAuthenticationFilter; import com.vibevault.security.JwtAuthenticationFilter;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer; import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
@ -17,9 +18,9 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
/** /**
* Spring Security 配置 * Spring Security 配置
* *
* 需要实现 * 需要实现:
* - 公开接口无需认证/api/auth/**, GET /api/playlists, GET /api/playlists/{id} * - 公开接口无需认证: /api/auth/**, GET /api/playlists, GET /api/playlists/{id}
* - 其他接口需要认证 * - 其他接口需要认证
* - 未认证访问受保护资源返回 401不是 403 * - 未认证访问受保护资源返回 401不是 403
* - 配置 JWT 过滤器 * - 配置 JWT 过滤器
@ -32,26 +33,68 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
public class SecurityConfig { public class SecurityConfig {
private final JwtAuthenticationFilter jwtAuthenticationFilter; private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final UserDetailsService userDetailsService;
public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) { // 构造注入过滤器和用户详情服务
public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter, UserDetailsService userDetailsService) {
this.jwtAuthenticationFilter = jwtAuthenticationFilter; this.jwtAuthenticationFilter = jwtAuthenticationFilter;
this.userDetailsService = userDetailsService;
} }
@Bean // 配置密码编码器
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// TODO: 配置安全规则
// 提示
// - 使用 http.authorizeHttpRequests() 配置路径权限
// - 使用 http.csrf(csrf -> csrf.disable()) 禁用 CSRF
// - 使用 http.sessionManagement() 配置无状态会话
// - 使用 http.exceptionHandling() 配置 401 响应
// - 使用 http.addFilterBefore() 添加 JWT 过滤器
return http.build();
}
@Bean @Bean
public PasswordEncoder passwordEncoder() { public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); return new BCryptPasswordEncoder();
} }
}
// 配置认证提供者
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
// 配置认证管理器
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
// 核心安全过滤链配置
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// 1. 禁用CSRFREST API不需要
.csrf(csrf -> csrf.disable())
// 2. 配置接口权限
.authorizeHttpRequests(auth -> auth
// 公开接口无需认证
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("GET", "/api/playlists").permitAll()
.requestMatchers("GET", "/api/playlists/{id}").permitAll()
// 其他接口需要认证
.anyRequest().authenticated()
)
// 3. 未认证返回401默认行为确保不被覆盖
.exceptionHandling(ex -> ex
.authenticationEntryPoint((request, response, authException) -> {
response.setStatus(401);
response.getWriter().write("Unauthorized: " + authException.getMessage());
})
)
// 4. 使用无状态会话JWT不需要会话
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
// 5. 配置JWT过滤器在用户名密码过滤器之前执行
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}