You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot 2.7禁用CSRF后SecurityFilterChain未调用UserDetailsService求助

问题解决:禁用CSRF同时触发HTTP Basic认证的UserDetailsService调用

核心问题分析

你的SecurityConfig里配置了.antMatchers("/**").permitAll(),这意味着所有请求都被允许无需认证,HTTP Basic认证的逻辑根本不会被触发,所以自定义的UserDetailsServiceImpl.loadUserByUsername()自然不会被调用。这和CSRF配置无关,是授权规则的错误导致的。

解决方案

修改SecurityFilterChain的授权规则,把permitAll()改成authenticated(),确保所有请求都需要经过HTTP Basic认证:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Autowired 
    private UserDetailsService userDetailsService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            // 替换permitAll为authenticated,要求所有请求必须认证
            .antMatchers("/**").authenticated()
            .and()
            // 禁用CSRF,解决POST 401问题
            .csrf().disable()
            // 启用HTTP Basic认证
            .httpBasic()
            .and()
            // 指定自定义的UserDetailsService
            .userDetailsService(userDetailsService);
        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

额外优化建议

  1. UserDetailsServiceImpl的错误修正:

    • 不要返回null,当用户名无效时直接抛出UsernameNotFoundException即可,返回null会导致Spring Security内部报错
    • 你当前用passwordEncoder.encode(username)生成密码,每次编码结果都不同,实际场景中应该从数据库读取已加密的密码,而不是实时编码。测试阶段可以固定一个加密后的密码,比如:
      // 测试用:假设密码是username对应的明文,提前加密一次
      String encryptedPwd = "$2a$10$..."; // 替换为BCrypt加密后的结果
      return new User(username, encryptedPwd, true, true, true, true, authList);
      
  2. 细化授权规则(可选):
    如果有不需要认证的路径(比如健康检查接口),可以单独放开:

    .antMatchers("/actuator/health").permitAll()
    .anyRequest().authenticated()
    

内容的提问来源于stack exchange,提问作者cocoz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 20:45:16