注册新用户后,数据库中生成的散列密码与输入的用户输入的密码不匹配,以便进行身份验证。原始密码是相同的,但散列版本是不同的。我想知道如何让这两个相互匹配以进行正确的身份验证?我正在使用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类中进行编码。将编码移动到用户创建的位置之后一切正常,因为编码现在只出现在用户创建过程中。谢谢!
答案 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;
}