如何在春季使用BCryptPasswordEncoder进行帐户注册和帐户身份验证?

时间:2015-03-18 08:14:06

标签: authentication spring-security spring-boot

我已经基于Spring-Boot 1.2.2.RELEASE创建了一个Web应用程序。我还有一个数据库表,用于管理用户凭据。它有基本列,例如ID,用户名和密码。还添加了盐柱,我计划在每个帐户存储随机生成的盐。

我正在尝试使用Spring Security,并且使用编码密码进行身份验证时遇到一些困难。所以基本上我有一个寄存器控制器:

@Autowired
private UserRepository userRepository;

private BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

@RequestMapping(value = "/register", method = RequestMethod.POST)
public ResponseEntity<User> register(@RequestParam(value = "email_address") String emailAddress, @RequestParam(value = "password") String password) {
    String username = emailAddress;
    String salt = KeyGenerators.string().generateKey(); 
    User user = new User();
    user.setUsername(emailAddress);
    user.setEmailAddress(emailAddress);
    user.setSalt(salt);
    user.setPassword(passwordEncoder.encode(username+salt+password));
    user.setCreatedBy(1);
    user.setCreatedOn(new Date());
    user.setLastUpdatedby(1);
    user.setLastUpdatedOn(new Date());
    user.setStartDate(new Date());
    return new ResponseEntity<User>(this.userRepository.save(user), HttpStatus.OK);
}

然后我实现了UserDetailsS​​ervice:

@Service
protected static class ApplicationUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = this.userRepository.findByUsername(username);

        if (user == null) {
            return null;
        }

        List<GrantedAuthority> auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER");

        String password = passwordEncoder.encode(username+user.getSalt()+user.getPassword());

        return new org.springframework.security.core.userdetails.User(username, password, auth);
    }
}

但是,由于BCryptPasswordEncoder每次都会生成新的结果,即使输入相同,它将如何进行身份验证?

修改 只是想补充一点,如果我不使用任何编码器并将密码存储为纯文本,我可以进行身份​​验证。但当然这不是我想做的事。

更新1 这是WebSecurityConfigurerAdapter的配置。在里面我有配置方法。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
protected static class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private ApplicationUserDetailsService applicationUserDetailsService;

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

  @Bean 
  @Override
  protected AuthenticationManager authenticationManager() throws Exception {
    return super.authenticationManager();
  }

}

更新2 我通过扩展DaoAuthenticationProvider来实现它。请参阅下面的更新代码。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
protected static class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ApplicationUserDetailsService applicationUserDetailsService;

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(applicationUserDetailsService);
        authenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder());
        return authenticationProvider;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider());
    }

    @Bean   
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

}

还必须修改我的RegisterController,如下所示。

@RestController
public class RegisterController {

  @Autowired
  private UserRepository userRepository;

  private BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

  @RequestMapping(value = "/register", method = RequestMethod.POST)
  public ResponseEntity<User> register(@RequestParam(value = "email_address") String emailAddress, @RequestParam(value = "password") String password) {
    User user = new User();
    user.setUsername(emailAddress);
    user.setEmailAddress(emailAddress);
    user.setPassword(passwordEncoder.encode(password));
    user.setSalt(KeyGenerators.string().generateKey());
    user.setCreatedBy(1);
    user.setCreatedOn(new Date());
    user.setLastUpdatedby(1);
    user.setLastUpdatedOn(new Date());
    user.setStartDate(new Date());
    return new ResponseEntity<User>(this.userRepository.save(user), HttpStatus.OK);
  }

}

更新3

忘记包含更新的UserDetailService实现。

@Service
protected static class ApplicationUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = this.userRepository.findByUsername(username);

        if (user == null) {
            return null;
        }

        List<GrantedAuthority> auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER");

        String password = passwordEncoder.encode(user.getPassword());

        return new org.springframework.security.core.userdetails.User(username, password, auth);
    }
}

我可能需要立即删除盐柱,因为它基本上没用。

希望这对其他人也有帮助。

0 个答案:

没有答案