Spring Security - 使用BCrypt哈希密码进行用户身份验证(错误的凭据错误)

时间:2016-12-10 05:24:18

标签: java spring spring-mvc authentication spring-security

注册新用户后,数据库中生成的散列密码与输入的用户输入的密码不匹配,以便进行身份验证。原始密码是相同的,但散列版本是不同的。我想知道如何让这两个相互匹配以进行正确的身份验证?我正在使用Spring 4.3.2.RELEASE和4.2.0.RELEASE for Security。

我也有警告:

WARN SpringSecurityCoreVersion:78 - **** You are advised to use Spring 4.3.4.RELEASE or later with this version. You are running: 4.3.0.RELEASE

也许这会以某种方式引起问题。

config.xml中:

<bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />

<security:authentication-manager>
    <security:authentication-provider user-service-ref="userService">
        <security:password-encoder ref="encoder"/>
    </security:authentication-provider>
</security:authentication-manager>

<bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <property name="userDetailsService" ref="userService" />
    <property name="hideUserNotFoundExceptions" value="false" />
    <property name="passwordEncoder" ref="encoder" />
</bean>

<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
    <constructor-arg>
        <ref bean="daoAuthenticationProvider" />
    </constructor-arg>
</bean>

UserEntity.java:

public void setPassword(String password) {
    BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    this.password = passwordEncoder.encode(password);
}

UserAuthenticationProviderService.java:

public boolean processUserAuthentication(UserEntity user) {

    try {
        Authentication request = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
        Authentication result = authenticationManager.authenticate(request);
        SecurityContextHolder.getContext().setAuthentication(result);

        return true;
    } catch(AuthenticationException e) {
        FacesContext.getCurrentInstance().addMessage(null, 
                new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), "Catched Error!"));

        return false;
    }
}
编辑:解决了。

正如Shaun所说,问题是在Entity类中进行编码。将编码移动到用户创建的位置之后一切正常,因为编码现在只出现在用户创建过程中。谢谢!

1 个答案:

答案 0 :(得分:0)

是的,您在BCryptEncoder对相同字符串进行2次编码后立即注意到,您将获得不同的字符串。但Spring Security不使用匹配等于。当您注册编码器时,SPring Security将使用PasswordEncoder中的boolean matches(CharSequence rawPassword, String encodedPassword)(BCryptEncoder实现此接口)。

如果您对细节感兴趣,可以查看BCrypt的实现,非常简单:

static boolean equalsNoEarlyReturn(String a, String b) {
        char[] caa = a.toCharArray();
        char[] cab = b.toCharArray();

        if (caa.length != cab.length) {
            return false;
        }

        byte ret = 0;
        for (int i = 0; i < caa.length; i++) {
            ret |= caa[i] ^ cab[i];
        }
        return ret == 0;
    }