Spring 当重新检查密码时,无法使Bcrypt哈希生效
我使用Bcrypt散列密码,并根据Spring文档使用Random。我使用的是SpringSecurity 3.2.5.0版本 我有以下OAuth2安全配置:Spring 当重新检查密码时,无法使Bcrypt哈希生效,spring,spring-security-oauth2,Spring,Spring Security Oauth2,我使用Bcrypt散列密码,并根据Spring文档使用Random。我使用的是SpringSecurity 3.2.5.0版本 我有以下OAuth2安全配置: <?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/security/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2.xsd">
<beans:bean id="userService" class="com.nando.api.service.DefaultUserService" />
<beans:bean id="webServiceClientService"
class="com.nando.api.service.DefaultWebServiceClientService" />
<beans:bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<beans:constructor-arg ref="webServiceClientService" />
</beans:bean>
<beans:bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" />
<beans:bean id="webSecurityExpressionHandler"
class="org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler" />
<beans:bean id="methodSecurityExpressionHandler"
class="org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler" />
<beans:bean id="passwordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<beans:bean id="tokenStore"
class="com.nando.api.service.DefaultAccessTokenService" />
<beans:bean id="oauthRequestFactory" class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<!-- TODO arguments here -->
<beans:constructor-arg name="clientDetailsService" ref="webServiceClientService" />
<!-- <beans:property name="securityContextAccessor" ref="oauthRequestFactory" /> -->
</beans:bean>
<beans:bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<beans:property name="tokenStore" ref="tokenStore" />
<!-- TODO here -->
<beans:property name="requestFactory" ref="oauthRequestFactory" />
</beans:bean>
<beans:bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<beans:bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint" />
<authentication-manager>
<authentication-provider user-service-ref="userService">
<password-encoder ref="passwordEncoder" />
</authentication-provider>
</authentication-manager>
<authentication-manager id="oauthClientAuthenticationManager">
<authentication-provider user-service-ref="clientDetailsUserService">
<password-encoder ref="passwordEncoder" />
</authentication-provider>
</authentication-manager>
<oauth2:authorization-server
token-services-ref="tokenStore" client-details-service-ref="webServiceClientService"
user-approval-page="oauth/authorize" error-page="oauth/error">
<oauth2:authorization-code />
</oauth2:authorization-server>
<beans:bean id="nonceServices"
class="com.nando.api.service.DefaultOAuthNonceService" />
<beans:bean id="resourceServerFilter"
class="com.nando.api.filters.OAuthSigningTokenAuthenticationFilter">
<beans:property name="authenticationEntryPoint" ref="oauthAuthenticationEntryPoint" />
<beans:property name="nonceServices" ref="nonceServices" />
<beans:property name="tokenStore" ref="tokenStore" />
<beans:property name="resourceId" value="nando" />
</beans:bean>
<global-method-security pre-post-annotations="enabled"
order="0" proxy-target-class="true">
<expression-handler ref="methodSecurityExpressionHandler" />
</global-method-security>
<http security="none" pattern="/resource/**" />
<http security="none" pattern="/favicon.ico" />
<http use-expressions="true" create-session="stateless"
authentication-manager-ref="oauthClientAuthenticationManager"
entry-point-ref="oauthAuthenticationEntryPoint" pattern="/oauth/token">
<intercept-url pattern="/oauth/token" access="hasAuthority('OAUTH_CLIENT')" />
<http-basic />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<expression-handler ref="webSecurityExpressionHandler" />
</http>
<http use-expressions="true" create-session="stateless"
entry-point-ref="oauthAuthenticationEntryPoint" pattern="/services/**">
<intercept-url pattern="/services/**"
access="hasAuthority('USE_WEB_SERVICES')" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<expression-handler ref="webSecurityExpressionHandler" />
</http>
<http use-expressions="true">
<intercept-url pattern="/session/list"
access="hasAuthority('VIEW_USER_SESSIONS')" />
<intercept-url pattern="/oauth/**"
access="hasAuthority('USE_WEB_SERVICES')" />
<intercept-url pattern="/login/**" access="permitAll()" />
<intercept-url pattern="/login" access="permitAll()" />
<intercept-url pattern="/logout" access="permitAll()" />
<intercept-url pattern="/**" access="isFullyAuthenticated()" />
<form-login default-target-url="/ticket/list" login-page="/login"
login-processing-url="/login/submit" authentication-failure-url="/login?loginFailed"
username-parameter="username" password-parameter="password" />
<logout logout-url="/logout" logout-success-url="/login?loggedOut"
delete-cookies="JSESSIONID" invalidate-session="true" />
<session-management invalid-session-url="/login"
session-fixation-protection="changeSessionId">
<concurrency-control error-if-maximum-exceeded="true"
max-sessions="1" session-registry-ref="sessionRegistry" />
</session-management>
<csrf />
<expression-handler ref="webSecurityExpressionHandler" />
</http>
</beans:beans>
其中:
private static final SecureRandom RANDOM;
static {
try {
RANDOM = SecureRandom.getInstanceStrong();
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e);
}
}
private static final int HASHING_ROUNDS = 10;
密码经过哈希处理并正确生成。它被正确地保存在数据库中,并被正确地检索。但是当它被检查时,呈现的密码不会被散列,因此比较失败
首先,this.saltSource为null,因为我没有定义盐bean。我认为这是随机的,盐是老办法
现在,当查看调试器时:
if (this.saltSource != null) {
salt = this.saltSource.getSalt(userDetails);
}
if (authentication.getCredentials() == null) {
logger.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails);
}
String presentedPassword = authentication.getCredentials().toString();
if (!passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) {
logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails);
}
presentedPassword没有散列,salt为空。所以!passwordEncoder.isPasswordValiduserDetails.getPassword、presentedPassword、salt测试检查失败
如果我使用的是随机盐,我如何才能让它起作用?我遗漏了什么?在我看来很好,isPasswordValid检查应该会调用到您的密码编码器中。我不太清楚你认为哪里出了问题。你是说你的密码编码器从未被调用?您如何确保密码正确存储?什么是转换器?你的UserDetails是如何从你创建的UserPrincipal中获取密码的?由于你有许多具有not pattern属性的blocs,因此只会使用第一个blocs…@SergeBallesta只有一个没有模式最后一个oneNow我也有同样的问题,在我切换到使用UserDetailsPrice of Spring之前,我使用的是JDBC,它可以正常工作,但我对Spring数据库模式不满意,所以我使用自定义方式检索UserEntity!
if (this.saltSource != null) {
salt = this.saltSource.getSalt(userDetails);
}
if (authentication.getCredentials() == null) {
logger.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails);
}
String presentedPassword = authentication.getCredentials().toString();
if (!passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) {
logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails);
}