使用Spring Boot等技术认证时遇Encoded password does not look like BCrypt错误求助
Hey there, let's sort out that frustrating Encoded password does not look like BCrypt error you're stuck on. This is a super common issue when working with Spring Security's BCrypt authentication, so let's break down the most likely causes and fixes based on your CustomDetailsService setup.
Common Causes & Solutions
1. The password returned by your CustomDetailsService isn't a valid BCrypt hash
BCrypt hashes have a very specific format: they start with $2a$, $2b$, or $2y$ and are exactly 60 characters long. If your loadUserByUsername method is returning a plaintext password, or a hash from a different algorithm (like MD5), Spring Security will throw this error.
Fix:
- First, check if the password stored in your database (via
userBo) is already a BCrypt hash. If not, you need to encrypt it before storing—ideally during user registration usingBCryptPasswordEncoder:// Example registration logic BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); user.setPassword(encoder.encode(plaintextPassword)); userBo.save(user); - If you're testing and need a quick fix (don't do this in production!), you can temporarily encode the password in your
loadUserByUsernamemethod:@Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userBo.findByUsername(username); if (user == null) { logger.error("User not found: {}", username); throw new UsernameNotFoundException("User not found"); } // Temporary encoding (for testing only!) BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); String encodedPassword = encoder.encode(user.getPassword()); // Build UserDetails with the encoded password return User.withUsername(user.getUsername()) .password(encodedPassword) .authorities(getUserAuthorities(user)) .accountExpired(false) .accountLocked(false) .credentialsExpired(false) .enabled(true) .build(); } private Collection<? extends GrantedAuthority> getUserAuthorities(User user) { // Fetch roles via roleBo and convert to GrantedAuthority return roleBo.findByUserId(user.getId()) .stream() .map(role -> new SimpleGrantedAuthority(role.getName())) .collect(Collectors.toList()); }
2. Your Spring Security config isn't using BCryptPasswordEncoder
Spring Security needs to know which password encoder you're using. If you haven't configured BCryptPasswordEncoder as a bean or linked it to your authentication manager, it won't recognize the BCrypt hash.
Fix:
Add the encoder bean to your security configuration class, and bind it to your UserDetailsService:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private CustomDetailsService customDetailsService; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customDetailsService) .passwordEncoder(passwordEncoder()); // Bind the encoder here } // Rest of your security config... }
For OAuth2 setups, make sure your token endpoint or client details also use this encoder if they handle password-based authentication.
3. Database password field is too short or corrupted
BCrypt hashes are 60 characters long. If your database's password column is shorter than that (e.g., VARCHAR(50)), the hash will get truncated, making it invalid. Corruption (like extra spaces or special characters stored with the hash) can also cause this error.
Fix:
- Check your user table's password column: set it to
VARCHAR(255)to be safe. - Manually verify the password in your database—ensure it starts with the BCrypt prefix and is exactly 60 characters, no extra whitespace.
4. Custom UserDetails implementation is modifying the password
If you're using a custom UserDetails class instead of Spring's built-in User, double-check that the getPassword() method returns the raw BCrypt hash from the database without any modifications (like decryption or string manipulation).
Fix:
Ensure your custom UserDetails class's getPassword() method directly returns the stored hash:
public class CustomUserDetails implements UserDetails { private String password; // Constructor, other methods... @Override public String getPassword() { return password; // No modifications here! } // Rest of the UserDetails methods... }
Final Check
Go back to your CustomDetailsService's loadUserByUsername method and confirm that every time you build a UserDetails object, the password passed to it is a valid BCrypt hash. That's usually where the problem lies.
内容的提问来源于stack exchange,提问作者Kunle Ajiboye

