繁体   English   中英

使用PasswordEncoder-盐的存储方式

[英]Using PasswordEncoder - How salt is stored

我为Spring启动应用程序使用了以下Web安全配置:

@EnableWebSecurity
@Configuration
class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired 
    private AccountRepository accountRepository;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
                .antMatchers("/login").permitAll()
            .and()
            .authorizeRequests()
                .antMatchers("/signup").permitAll()
            .and()
            .authorizeRequests()
                .anyRequest().authenticated()
            .and()
                .logout().logoutUrl("/logout").logoutSuccessUrl("/login").deleteCookies("auth_code").invalidateHttpSession(true)
            .and()
            // We filter the api/signup requests
            .addFilterBefore(
                new JWTSignupFilter("/signup", authenticationManager(), accountRepository),
                UsernamePasswordAuthenticationFilter.class)
            // We filter the api/login requests
            .addFilterBefore(
                new JWTLoginFilter("/login", authenticationManager()),
                UsernamePasswordAuthenticationFilter.class)
            // And filter other requests to check the presence of JWT in
            // header
            .addFilterBefore(new JWTAuthenticationFilter(userDetailsServiceBean()),
                UsernamePasswordAuthenticationFilter.class);
    }

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

    @Override
    public UserDetailsService userDetailsServiceBean() throws Exception {
        return new CustomUserDetailsService(accountRepository);
    }

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

如您所见,我使用BCryptPasswordEncoder。

我有两个问题:

1. BCryptPasswordEncoder的盐存储在哪里? 根据我的发现,它每次都是随机的,并且存储在数据库中的某个位置,但是我没有为其定义任何列。 我对它的工作方式感到困惑。

2.我有一个注册过滤器:

public class JWTSignupFilter extends AbstractAuthenticationProcessingFilter {

    private AccountRepository accountRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    public JWTSignupFilter(String url, AuthenticationManager authManager,
            AccountRepository accountRepository) {
        super(new AntPathRequestMatcher(url, "POST"));
        setAuthenticationManager(authManager);
        this.accountRepository = accountRepository;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest req,
            HttpServletResponse res) throws AuthenticationException,
            IOException, ServletException {

        CustomUserDetails creds = new ObjectMapper().readValue(
                req.getInputStream(), CustomUserDetails.class);

        if (accountRepository.findByUsername(creds.getUsername()) != null) {
            throw new AuthenticationException("Duplicate username") {
                private static final long serialVersionUID = 1L;
            };
        }

        CustomUserDetails userDetails = new CustomUserDetails(
                creds.getUsername(), creds.getPassword(), true, true, true,
                true,
                AuthorityUtils.commaSeparatedStringToAuthorityList("USER_ROLE"));

        accountRepository.save(userDetails);

        return getAuthenticationManager().authenticate(
                new UsernamePasswordAuthenticationToken(creds.getUsername(),
                        creds.getPassword()));
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest req,
            HttpServletResponse res, FilterChain chain, Authentication auth) {
        TokenAuthenticationService.addAuthentication(res, auth.getName());
    }
}

如您所见,我创建了一个新的UserDetails并将其保存在帐户存储库中。

如果我在创建UserDetails对象时对密码进行编码,它将创建与登录时不同的密码。(认为密码不同)我认为这应该是因为使用了不同的盐。

知道我该如何解决吗?

Bcrypt 包含电池 :通常保存在数据库中的文本包含salt和迭代次数。 在线生成器可以显示它。 例如,给定秘密P@ssw0rd这里是序列化方式(4次迭代):

$2a$04$tpwXnhoO89cja8UZw3.hpulcAGzL1ps5cqzTLubh60csfEwna4N3W
$2a$04$VuLYo3y8e1ZITJPgW8LliOzdRa220D0frl5oSPQeFxAOlmvmsTCsK
$2a$04$bkChnYI84W3P3DW8YZrQc.yarPrW9kCDRAEp8ZKlap2BiO2Y.ThNa
...

引用这个答案

  • 2a标识bcrypt算法版本
  • 04是成本因素; 2使用密钥推导函数的4次迭代
  • vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa是盐和密文,在改进的Base-64中进行连接和编码。 前22个字符解码为salt的16字节值。 其余字符是要进行身份验证的密文。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM