首页 > 解决方案 > 实施 Bcrypt PasswordEncoder 后无法使用身份验证

问题描述

实施 Bcrypt 密码编码器后,我无法进行身份验证(凭据无效)。这是我要添加的用户:

userRepository.save(new User("First", "Last", "user", "user" , "email@email.com", "12345", superRoles));

当我查看页面的 JSON 时,我看到密码是散列的。但是,当我尝试输入密码“用户”时,我无法进行身份验证:

..."password": "$2a$10$ZwUxEGVDAgI4qgkas0bEO.BmU1WrMXk1zQA5Jc70m.e6reiL3M7BG"...

谁能发现我做错了什么?代码贴在下面。先感谢您!

用户等级:

@Entity
public class User {
    public static final PasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();
    private long userId;
    private String userFirstName;
    private String userLastName;
    private String username;
    private String password;
    private String userPhone;
    private String userEmail;
    //others, such as List for roles, etc.

    public User() { }

    public User(String userFirstName, String userLastName, String username, String password, String userPhone, String userEmail, Map<String, Boolean> userRoles) {
        this.userFirstName = userFirstName;
        this.userLastName = userLastName;
        this.username = username;
        setPassword(password);
        this.userPhone = userPhone;
        this.userEmail = userEmail;
        this.userRoles = userRoles;
    }
    public void setPassword(String password) {
        this.password = PASSWORD_ENCODER.encode(password);
    }
        // other getters and setters
}

网络安全配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    DetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(User.PASSWORD_ENCODER);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                    .antMatchers(
                            "/login"
                    ).permitAll()
...
// taken out for brevity
    }
}

详情服务:

@Component
public class DetailsService implements UserDetailsService {
    @Autowired
    UserRepository users;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = users.findByUsername(username);
        // Roles are implemented in the entity in a Map<String, Boolean>, e.g. "ROLE_ADMIN" : true, to help with easily setting new permissions on the front end
        List<String> roles = new ArrayList<>();

        for (Map.Entry<String, Boolean> entry : user.getUserRoles().entrySet()) {
            if (entry.getValue().equals(true)) {
                roles.add(entry.getKey());
            }
        }

        String[] permissions = roles.toArray(new String[roles.size()]);

        if (user == null) {
            throw new UsernameNotFoundException(username + " was not found");
        }
        return new org.springframework.security.core.userdetails.User(
                user.getUsername(),
                user.getPassword(),
                AuthorityUtils.createAuthorityList(permissions)
        );
    }
}

编辑2:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers(
                        "/login",
                        "/home",
                        "/visitor-area",
                        "/site.css",
                        "/app.js",
                        "/create-account",
                        "/css/*",
                        "/saveUser",
                        "/users"
                ).permitAll()
            .and()
            .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/user-dashboard")
            .and()
            .logout()
                .permitAll()
                .logoutSuccessUrl("/home")
            .and()
            .csrf().disable();
    }

标签: javaspringspring-bootbcrypt

解决方案


解决了:

当我加密User实体上的密码时,它不会进行身份验证。为了解决这个问题,我在构造函数中恢复了常规String password的 getter/setter setPassword(password)。然后,在实现的类中ApplicationRunner,我在那里对密码进行了编码:

    String password = "user";
    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    String hashedPassword = passwordEncoder.encode(password);

    userRepository.save(new User("First", "Last", "user", hashedPassword , "email@email.com", "12345", superRoles));

推荐阅读