macrozheng/mall-learning · error · BadCredentialsException
密码不正确
Error message
密码不正确
What it means
UmsAdminServiceImpl.login throws BadCredentialsException('密码不正确') when passwordEncoder.matches(password, userDetails.getPassword()) fails — i.e. the submitted BCrypt hash does not match the stored hash. This is Spring Security's standard signal for a wrong password during programmatic login. Note the catch block immediately swallows it (catch AuthenticationException) and returns an empty token, so callers often see null/empty token instead of the exception itself.
Solutions
- Re-enter/reset the password; reset via UPDATE ums_admin SET password = '{bcrypt}...' with a properly BCrypt-encoded value
- Verify stored passwords are BCrypt-encoded (start with $2a$/$2b$); re-encode seed data if not
- Confirm the PasswordEncoder bean matches how passwords were created (same encoder for register and login)
- Check that the catch block does not silently mask the failure; log/return a clear error to the caller
Example fix
// before
if (!passwordEncoder.matches(password, userDetails.getPassword())) {
throw new BadCredentialsException("密码不正确");
}
// after
if (!passwordEncoder.matches(password, userDetails.getPassword())) {
log.warn("Wrong password for user: {}", username);
throw new BadCredentialsException("密码不正确");
} Defensive patterns
Strategy: try-catch
Validate before calling
// client-side: require non-empty password before submit
if (!password || password.length < 6) throw new Error('密码不能为空');
// server-side sanity: stored hash must look like BCrypt
String stored = userDetails.getPassword();
boolean looksBcrypt = stored != null && (stored.startsWith("$2a$") || stored.startsWith("$2b$") || stored.startsWith("{bcrypt}"));
if (!looksBcrypt) log.error("Stored password for {} is not BCrypt-encoded", username); Try / catch
try {
String token = adminService.login(username, password);
if (token == null || token.isEmpty()) {
throw new ApiException("用户名或密码错误");
}
} catch (BadCredentialsException e) {
throw new ApiException("密码不正确");
} Prevention
- Always encode passwords with the same PasswordEncoder used at login
- Never insert plaintext or MD5 passwords into ums_admin
- If you change the encoder, migrate all stored hashes
- Don't silently swallow AuthenticationException in login(); return a clear error
- Wrap DB-edited passwords with {bcrypt} prefix or re-encode them
When it happens
Trigger: POST /admin/login with a valid username but a password whose BCrypt hash does not match ums_admin.password.
Common situations: User typo in password, admin row created with a plaintext or differently-encoded password (so BCrypt matches always fail), seed data inserted without BCrypt encoding, password changed in DB directly, wrong encoder bean configured (e.g. changing PasswordEncoder after users were created).
Related errors
AI-assisted analysis of macrozheng/mall-learning@cd02c000e5 (2026-09-07).
Data as JSON: /api/errors/5673f766b383d55b.
Report an issue: GitHub.
Appendix: source
Thrown at mall-tiny-04/src/main/java/com/macro/mall/tiny/service/impl/UmsAdminServiceImpl.java:106
}
return null;
}
@Override
public List<UmsResource> getResourceList() {
return resourceList;
}
@Override
public String login(String username, String password) {
String token = null;
try {
UserDetails userDetails = getAdminByUsername(username);
if(userDetails==null){
return token;
}
if (!passwordEncoder.matches(password, userDetails.getPassword())) {
throw new BadCredentialsException("密码不正确");
}
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
token = jwtTokenUtil.generateToken(userDetails);
} catch (AuthenticationException e) {
log.warn("登录异常:{}", e.getMessage());
}
return token;
}
}
View on GitHub (pinned to cd02c000e5)