Spring Security基础认证始终返回403 Forbidden问题排查
Spring Boot 3.0.2 基础认证返回403的问题分析与修复
核心问题1:Spring Security 6.x 配置API过时
你的配置中使用了authorizeRequests(),这是Spring Security 5.x的旧API,在Spring Boot 3.x(对应Spring Security 6.x)中已被弃用,替换为authorizeHttpRequests()。过时API会导致权限规则不生效,直接返回403。
核心问题2:单元测试逻辑错误
测试方法存在两处明显问题:
- 手动构造
TestingAuthenticationToken跳过了Spring Security的密码校验流程,无法真实模拟认证场景;且你用明文密码构造UserDetails,但系统中实际存储的是BCrypt加密后的密码,两者不匹配。 - 测试用的是正确密码
password,却期望返回401 Unauthorized,逻辑完全矛盾。
修复方案
1. 修正Security配置类
更新为Spring Security 6.x的标准配置方式:
@Configuration @EnableWebSecurity public class WebSecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // 替换过时的authorizeRequests为authorizeHttpRequests http.authorizeHttpRequests(auth -> auth .anyRequest().authenticated()) .httpBasic(Customizer.withDefaults()); // 简化httpBasic配置写法 return http.build(); } @Bean public InMemoryUserDetailsManager userDetailsService() { UserDetails user = User .withUsername("user") .password(passwordEncoder().encode("password")) .roles("USER") // roles方法会自动添加ROLE_前缀,最终权限为ROLE_USER .build(); return new InMemoryUserDetailsManager(user); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(8); } }
2. 修正单元测试
使用MockMvc原生的httpBasic()方法模拟HTTP基础认证,正确构造认证失败场景:
@Slf4j @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @RunWith(SpringRunner.class) @Transactional @AutoConfigureMockMvc class PdfReceiptControllerTest extends BaseTest { @Autowired private PdfDocumentRepositoryImpl pdfDocumentRepository; @Autowired protected MockMvc mockMvc; @Test void createReceipt_wrongPassword_unauthorized() throws Exception { // 传入错误密码,模拟认证失败 mockMvc.perform(post("/person/100") .httpBasic("user", "wrong-password")) .andExpect(status().isUnauthorized()); } // 可选:新增正确密码的验证测试 @Test void createReceipt_correctPassword_success() throws Exception { mockMvc.perform(post("/person/100") .httpBasic("user", "password")) .andExpect(status().isOk()); // 根据接口实际返回状态调整 } }
3. Postman调用验证
修复配置后,在Postman中选择Authorization标签,类型选Basic Auth,输入用户名user和密码password,即可正常访问接口。
内容的提问来源于stack exchange,提问作者LDropl
相关产品推荐
相关产品推荐

