首页 > 解决方案 > Spring Security 如何从 PasswordEncoder 获取用户名?

问题描述

添加新用户时,我将他的密码保存在数据库中,格式为 SHA256(cleartext_password + salt)。我为每个用户在单独的列中保存的盐值。因此,密码检查应按如下方式执行:我们从 BasicAuth 标头中提取密码明文,从数据库中获取该用户的 salt 值,执行 SHA256(cleartext_password + salt)并检查结果字符串和密码是否存储在数据库匹配。为了实现这一点,我创建了一个将执行验证的自定义 PasswordEncoder,但我无法从 PasswordEncoder 访问用户名。我需要用户名来为该用户获取盐并执行验证。我怎样才能摆脱这种情况?

这是安全性的当前实现:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final UserDetailsService customUserDetailsService;

    public SecurityConfig(UserDetailsService customUserDetailsService) {
        this.customUserDetailsService = customUserDetailsService;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
                .anyRequest().authenticated()
                .and().httpBasic();
    }

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

}

@Component
public class CustomUserDetailsService implements UserDetailsService {
    private final UserRepository userRepository;

    public CustomUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUserName(username);
        if (user != null) {
            return org.springframework.security.core.userdetails.
                    User.withUsername(username)
                    .password(new CustomPasswordEncoder().encode(user.getPassword()))
                    .roles("USER")
                    .build();
        }
        throw new IllegalArgumentException();
    }
}

public class CustomPasswordEncoder implements PasswordEncoder {

    @Override
    public String encode(CharSequence rawPassword) {
        return rawPassword.toString();
    }

    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        String sha256hex = DigestUtils.sha256Hex(rawPassword.toString()); // Here should be DigestUtils.sha256Hex(rawPassword.toString() + salt)
        return sha256hex.equals(encodedPassword);
    }

}

标签: javaspringspring-security

解决方案


推荐阅读