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

整合BCrypt与Hibernate的Spring Security返回Bad Credentials异常

问题分析与解决

嘿,我一眼就揪出你代码里的问题了!这绝对是导致你一直触发「Bad Credentials」异常的核心原因——你在JWTAuthenticationFilter的attemptAuthentication方法里,把用户名同时当作了密码传入认证请求!

错误代码位置

看这段代码:

@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException {
    try {
        User creds = new ObjectMapper()
                .readValue(req.getInputStream(), User.class);
        return authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(
                creds.getUsername(), 
                creds.getUsername(), // 这里是错误的!应该是creds.getPassword()
                new ArrayList<>())
        );
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

你创建UsernamePasswordAuthenticationToken时,第二个参数应该是用户提交的密码,但你却传了两次creds.getUsername()。这就导致Spring Security会拿数据库里的BCrypt加密密码,和你传入的用户名(明文)做比对,结果肯定不匹配,直接触发认证失败。

修复方法

把第二个参数改成creds.getPassword():

return authenticationManager.authenticate(
    new UsernamePasswordAuthenticationToken(
        creds.getUsername(), 
        creds.getPassword(), // 修正为获取密码
        new ArrayList<>())
);

额外检查点(避免后续踩坑)

修复上面的问题后,建议再确认以下几点:

  • 注册时密码必须加密存储:确保你在用户注册接口里,是用BCryptPasswordEncoder对原始密码加密后再存入数据库的,比如:
    user.setPassword(bCryptPasswordEncoder.encode(rawPassword));
    repository.save(user);
    
  • 数据库密码一致性:检查数据库中存储的密码确实是BCrypt加密后的字符串(格式通常是$2a$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),不是明文。
  • 用户名大小写问题:Spring Security默认对用户名的匹配是区分大小写的,如果你需要忽略大小写,可以在UserDetailsServiceImpl里查询用户名时统一转成小写(比如repository.findByUsername(username.toLowerCase())),同时注册时也要统一处理。

你的完整代码参考(修正后)

修正后的JWTAuthenticationFilter核心部分

@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException {
    try {
        User creds = new ObjectMapper()
                .readValue(req.getInputStream(), User.class);
        return authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(
                creds.getUsername(), 
                creds.getPassword(), 
                new ArrayList<>())
        );
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:58:38