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

Spring Security数据库用户登录遇401/403错误求助

问题分析与解决方案

问题根源

  1. 保留httpBasic()时触发401:HttpBasic认证要求所有需认证的请求在请求头携带Authorization: Basic <base64编码的用户名密码>,但你是通过自定义/login接口完成认证的,并未走HttpBasic认证流程,后续访问GET接口时,HttpBasic过滤器检测不到合法认证信息,返回401。
  2. 去掉httpBasic()时触发403:常见两种原因:
    • 登录后的认证状态未正确保持:Spring Security默认通过会话保存认证信息,若后续请求未携带会话Cookie,SecurityContext中无认证用户,导致403。
    • 用户权限配置问题:数据库中用户角色格式不符合Spring Security要求,或UserDetails返回的权限信息不正确。

具体解决方案

1. 调整SecurityConfig配置

适配自定义登录接口,关闭HttpBasic,确保会话管理正常,明确放行登录接口:

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
    private final CustomizedUserDetailsService customizedUserDetailsService;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // 关闭HttpBasic,使用自定义登录接口
                .httpBasic(AbstractHttpConfigurer::disable)
                .csrf().disable()
                // 会话管理保持默认的IF_REQUIRED,确保登录后会话生效
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED))
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/auth/**", "/login").permitAll() // 放行登录和注册相关接口
                        .anyRequest().authenticated()) // 其他所有请求需要认证
                // 指定自定义用户详情服务
                .userDetailsService(customizedUserDetailsService);
        return httpSecurity.build();
    }

    @Bean
    public AuthenticationManager authenticationManager(
            AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

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

2. 修复CustomizedUserDetailsServiceImpl细节

  • 密码加密检查:注册用户时,必须通过passwordEncoder().encode()加密密码后存入数据库,BCryptPasswordEncoder无法匹配明文密码。
  • 角色格式修正:Spring Security默认要求角色权限以ROLE_为前缀(如ROLE_USER),可在mapToGrantedAuthority方法中统一添加前缀:
private Collection<GrantedAuthority> mapToGrantedAuthority(List<Role> roles){
    return roles.stream()
            .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getAuthority()))
            .collect(Collectors.toList());
}
  • User对象构造修正:确保返回的User对象使用数据库查询到的用户名,避免参数名一致导致的潜在问题:
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    UserEntity user = repository.findByusername(username)
            .orElseThrow(() -> new UsernameNotFoundException("user doesn't exist in our database."));
    // 使用user.getUsername()而非传入的username参数
    return new User(user.getUsername(), user.getPassword(), mapToGrantedAuthority(user.getRoles()));
}

3. 确保认证状态保持

登录成功后,后续请求需携带会话Cookie(浏览器自动处理,Postman等工具需开启Cookie保存功能),Spring Security会通过会话ID从服务器端获取认证信息。若为前后端分离场景,后续可考虑引入JWT,初学者先从会话认证入手更易理解。

适合初学者的Spring Security学习资源

  • Spring官方文档入门章节:权威免费,包含从基础认证到权限控制的逐步教程,覆盖核心概念。
  • Spring Security官方示例项目:可直接克隆运行,包含内存用户、数据库用户、OAuth2等多种场景的实现代码,便于对照学习。
  • 《Spring Security实战》书籍:面向初学者的实战型书籍,讲解通俗易懂,配有大量可落地的代码案例。
  • 入门系列视频教程:各大技术平台上的从零搭建Spring Security系列视频,跟着敲代码快速掌握核心流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 17:56:06