java - Spring Security 和 BCryptPasswordEncoder 用于注册和登录

标签 java spring passwords bcrypt encoder

我是 Java Spring 新手,我想创建一个用户注册系统,该系统存储在我的数据库(Postgres)中,其中密码由 BCryptPasswordEncoder 加密存储。注册过程工作正常,但当我想登录时,我总是收到“无效的用户名或密码”。信息。我已经到处搜索并阅读了很多文章,但我所做的一切都得到了相同的结果。

这是我的 SecurityConfiguration 类:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    @Qualifier("customUserDetailsService")
    private CustomUserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
         auth.userDetailsService(userDetailsService()).and().authenticationProvider(authProvider());
    }
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/signin", "/confirm", "/error","/signup", "/css/**","/js/**","/images/**").permitAll()
            .antMatchers("/admin/**").hasAuthority("ROLE_ADMIN")
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/signin")
            .usernameParameter("username").passwordParameter("password")
            .defaultSuccessUrl("/cockpit.html")
            .permitAll()
            .and()
            .exceptionHandling().accessDeniedPage("/403")
            .and()
            .csrf()
            .and()
            .logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/signin").and().exceptionHandling()
            .accessDeniedPage("/error");
}


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


    @Bean
    public DaoAuthenticationProvider authProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(encoder());
        return authProvider;
    }
}

这是我的 CustomUserDetailsS​​ervice 类:

@Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService{
    private final UserRepository userRepository;
    private final RoleRepository userRolesRepository;

    @Autowired
    private PasswordEncoder bCryptPasswordEncoder;

    @Autowired
    public CustomUserDetailsService(UserRepository userRepository,RoleRepository userRolesRepository) {
        this.userRepository = userRepository;
        this.userRolesRepository=userRolesRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws 
    UsernameNotFoundException {

        Logger LOGGER = Logger.getLogger(CustomUserDetailsService.class.getName());
        User user = userRepository.findByUsername(username);
        if (null == user) {
            return null;
        } else {
            List<GrantedAuthority> authorities =             
            buildUserAuthority(userRolesRepository.findRoleByUserName(username));
            LOGGER.info("Loaded account: " + user.getUsername() + " password: " + user.getPassword() + " password matches: " + bCryptPasswordEncoder.matches("password", user.getPassword()));
            org.springframework.security.core.userdetails.User userDetails = new org.springframework.security.core.userdetails.User(user.getUsername(), Deuser.getPassword(),authorities);
            return userDetails;
        }
    }

    private List<GrantedAuthority> buildUserAuthority(Set<Role> userRoles) {

        Set<GrantedAuthority> setAuths = new HashSet<>();

        // add user's authorities
        for (Role userRole : userRoles) {
            setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
        }

        return new ArrayList<>(setAuths);


    }


    public User findByConfirmationToken(String confirmationToken) {
        return userRepository.findByConfirmationToken(confirmationToken);
    }

    public void saveUser(User user){
        user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
        userRepository.save(user);
    }

    public void saveRole(User user) {
        Role role = new Role();
        role.setRole("ROLE_USER");
        role.setId(user.getId());
        role.setUsername(user.getUsername());
        userRolesRepository.save(role);
    }
}

我在注册期间调用方法 saveUser(user) 和 saveRole(user) 。 LOGGER.info 消息为 bCryptPasswordEncoder.matches("password", user.getPassword()) 提供了“false”,即使我写了正确的密码。

已解决 好吧,我刚刚发现哪里错了。我在注册期间调用了两次 saveUser 方法,然后在激活期间调用了两次方法,因此密码被加密了两次。我通过添加方法 updateUser 而不使用加密解决了这个问题。

感谢您的帮助。

最佳答案

尝试这样:

@Override
          protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            // Create a default account
            auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
          }

自定义用户详细信息:

@Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User account = userDao.getUserByUsername(username);
        System.out.println("User got from DB----------------------" + account.getPassword());
        boolean enabled = true;
        boolean accountNonExpired = true;
        boolean credentialsNonExpired = true;
        boolean accountNonLocked = true;

        User user = new User(account.getUserName(), account.getPassword(), enabled, accountNonExpired,
                credentialsNonExpired, accountNonLocked, getAuthorities(account.getRole()));

        System.out.println(user.getPassword());
        return user;
    }

关于java - Spring Security 和 BCryptPasswordEncoder 用于注册和登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47158112/

相关文章:

带有 getPass 的 Rmarkdown 密码

MySQL/phpMyAdmin 重置 ROOT 密码?

正则表达式验证具有字符限制的密码

java - 使用 JXL 从 src 文件夹读取 Excel

java - 通过 POST 从 Angular 向 Springboot 发送数据

java - 如何将 POJO 的属性绑定(bind)到内部 ArrayList<ANOTHER_POJO> 的字段之和

java - Spring 按类型列出 bean

java - 从 Spring MVC - DAO 项目迁移到 Spring Boot

java - 在 Android Studio 中实现 ArrayList 的最佳方式

java.lang.IllegalStateException : No transactional EntityManager available