如何将密码文本与bcrypt哈希值进行比较?

14

我的应用程序中有一个使用案例,当用户重置密码时,应该防止用户选择他们最近的3个密码之一。我在前端使用Angular,后端使用Spring Boot。在我的场景中,用户密码以bcrypt哈希形式存储。

如何将用户输入的密码与最近存储的3个bcrypt密码进行比较?

当我运行以下代码示例片段时:

BCryptPasswordEncoder b = new BCryptPasswordEncoder();

    for(int i =0;i<10;i++) {
        System.out.println(b.encode("passw0rd"));

    }
它生成以下bcrypt哈希值。每个哈希值都不同,这是合理的,因为当我检查org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder时,我可以看到生成的盐是随机值。

它生成以下 bcrypt 哈希值。每个哈希值都不同,这很合理,因为当我检查 org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder 时,我可以看到生成的盐是随机值。

$2a$10$tztZsPFZ.T.82Gl/VIuMt.RDjayTwuMLAkRkO9SB.rd92vHWKZmRm
$2a$10$yTHyWDmcCBq3OSPOxjj4TuW9qXYE31CU.fFlWxppii9AizL0lKMzO
$2a$10$Z6aVwg.FNq/2I4zmDjDOceT9ha0Ur/UKsCfdADLvNHiZpR7Sz53fC
$2a$10$yKDVeOUvfTQuTnCHGJp.LeURFcXK6JcHB6lrSgoX1pRjxXDoc8up.
$2a$10$ZuAL06GS7shHz.U/ywb2iuhv2Spubl7Xo4NZ7QOYw3cHWK7/7ZKcC
$2a$10$4T37YehBTmPWuN9j.ga2XeF9GHy6EWDhQS5Uc9bHvJTK8.xIm1coS
$2a$10$o/zxjGkArT7YdDkrk5Qer.oJbZAYpJW39iWAWFqbOhpTf3FmyfWRC
$2a$10$eo7yuuE2f7XqJL8Wjyz.F.xj78ltWuMS1P0O/I6X7iNPwdsWMVzu6
$2a$10$3ErH2GtZpYJGg1BhfgcO/uOt/L2wYg4RoO8.fNRam458WWdymdQLW
$2a$10$IksOJvL/a0ebl4R2/nbMQ.XmjNARIzNo8.aLXiTFs1Pxd06SsnOWa

Spring安全配置。

  @Configuration
    @Import(SecurityProblemSupport.class)
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

        @PostConstruct
        public void init() {
            try {
                authenticationManagerBuilder
                    .userDetailsService(userDetailsService)
                    .passwordEncoder(passwordEncoder());
            } catch (Exception e) {
                throw new BeanInitializationException("Security configuration failed", e);
            }
        }
       @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    }
5个回答

36

您可以在 BCryptPasswordEncoder 中使用 matches 方法,类似于以下内容:

b.matches("passw0rd", hash)

1
这是解决方案,你能帮我理解Spring Security如何匹配存储在数据库中的哈希密码和用户提供的文本密码吗?当然,在编码后,它们将是不同的哈希值!!! - Sumon Bappi

4

实际上,我找到了答案。 我意识到可以在类org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder中使用matches函数。

System.out.println(b.matches("passw0rd", "$2a$10$tztZsPFZ.T.82Gl/VIuMt.RDjayTwuMLAkRkO9SB.rd92vHWKZmRm"));

这是解决方案,你能帮我理解Spring Security如何匹配存储在数据库中的哈希密码和用户提供的文本密码吗?当然,在编码后,它们将是不同的哈希值!!! - Sumon Bappi

2

Spring Security会从之前生成的哈希值中读取盐,并再次使用相同的盐对输入密码进行哈希。然后比较两个最终的哈希值,显然它们将是相同的。

例如:

密码:test

哈希:$2a$10$nCgoWdqJwQs9prt7X5a/2eWLn88I8pon6iNat90u4rq4mHqtoPGQy

哈希有3个部分,每个部分由$符号分隔。2a是Bcrypt的版本,10是总轮数,nCgoWdqJwQs9prt7X5a/2e是盐。

因此,Spring Security会使用密码test和盐nCgoWdqJwQs9prt7X5a/2e运行哈希方法。显然,它生成的哈希与密码和盐匹配。


0

请尝试以下方法:

  BCryptPasswordEncoder bc = new BCryptPasswordEncoder();
     boolean passChecker = bc.matches("Normal Password Here", "Hashed Password Here");

0

我曾经面临这样的情况,需要验证我的旧密码。旧密码存储在数据库中,并使用BCrypt加密。目的是为了修改密码。最终,我采用了如下方式进行操作。

BCryptPasswordEncoder b = new BCryptPasswordEncoder();
            if(b.matches(oldNormalPassword, #Password)){ // code ...}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接