此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Security 6.4.3! |
身份验证迁移
以下步骤与身份验证执行方式的更改有关。
在 Remember Me 中使用 SHA-256
这TokenBasedRememberMeServices
实现现在支持将 SHA-256 作为“记住我”令牌,这是 Spring Security 6 中的默认值。
默认情况下,此更改使实现更加安全,因为 MD5 已被证明是一种弱哈希算法,容易受到冲突攻击和模块化差分攻击。
新生成的令牌现在具有用于生成令牌的算法的信息,并且使用该信息来匹配它。
如果算法名称不存在,则matchingAlgorithm
属性用于检查 Token。
这允许从 MD5 到 SHA-256 的平稳过渡。
要选择使用新的 Spring Security 6 默认值对令牌进行编码,同时仍然能够解码使用 MD5 编码的令牌,你可以设置encodingAlgorithm
property 设置为 SHA-256,并将matchingAlgorithm
属性设置为 MD5。
有关更多信息,请参阅参考文档和 API 文档。
-
Java
-
XML
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http, RememberMeServices rememberMeServices) throws Exception {
http
// ...
.rememberMe((remember) -> remember
.rememberMeServices(rememberMeServices)
);
return http.build();
}
@Bean
RememberMeServices rememberMeServices(UserDetailsService userDetailsService) {
RememberMeTokenAlgorithm encodingAlgorithm = RememberMeTokenAlgorithm.SHA256;
TokenBasedRememberMeServices rememberMe = new TokenBasedRememberMeServices(myKey, userDetailsService, encodingAlgorithm);
rememberMe.setMatchingAlgorithm(RememberMeTokenAlgorithm.MD5);
return rememberMe;
}
}
<http>
<remember-me services-ref="rememberMeServices"/>
</http>
<bean id="rememberMeServices" class=
"org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="myUserDetailsService"/>
<property name="key" value="springRocks"/>
<property name="matchingAlgorithm" value="MD5"/>
<property name="encodingAlgorithm" value="SHA256"/>
</bean>
在某些时候,您将希望完全迁移到 Spring Security 6 默认值。但是你怎么知道什么时候这样做是安全的呢?
假设您在 11 月 1 日使用 SHA-256 作为编码算法(就像您在此处所做的那样)部署了应用程序,如果您有tokenValiditySeconds
属性设置为 N 天(默认值为 14)时,您可以在 11 月 1 日(在本例中为 11 月 15 日)之后的 N 天迁移到 SHA-256。
到那时,使用 MD5 生成的所有令牌都将过期。
-
Java
-
XML
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http, RememberMeServices rememberMeServices) throws Exception {
http
// ...
.rememberMe((remember) -> remember
.rememberMeServices(rememberMeServices)
);
return http.build();
}
@Bean
RememberMeServices rememberMeServices(UserDetailsService userDetailsService) {
RememberMeTokenAlgorithm encodingAlgorithm = RememberMeTokenAlgorithm.SHA256;
TokenBasedRememberMeServices rememberMe = new TokenBasedRememberMeServices(myKey, userDetailsService, encodingAlgorithm);
rememberMe.setMatchingAlgorithm(RememberMeTokenAlgorithm.SHA256);
return rememberMe;
}
}
<http>
<remember-me services-ref="rememberMeServices"/>
</http>
<bean id="rememberMeServices" class=
"org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="myUserDetailsService"/>
<property name="key" value="springRocks"/>
<property name="matchingAlgorithm" value="SHA256"/>
<property name="encodingAlgorithm" value="SHA256"/>
</bean>
如果您在使用 Spring Security 6 默认值时遇到问题,则可以使用以下配置显式选择加入 5.8 默认值:
-
Java
-
XML
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http, RememberMeServices rememberMeServices) throws Exception {
http
// ...
.rememberMe((remember) -> remember
.rememberMeServices(rememberMeServices)
);
return http.build();
}
@Bean
RememberMeServices rememberMeServices(UserDetailsService userDetailsService) {
RememberMeTokenAlgorithm encodingAlgorithm = RememberMeTokenAlgorithm.MD5;
TokenBasedRememberMeServices rememberMe = new TokenBasedRememberMeServices(myKey, userDetailsService, encodingAlgorithm);
rememberMe.setMatchingAlgorithm(RememberMeTokenAlgorithm.MD5);
return rememberMe;
}
}
<http>
<remember-me services-ref="rememberMeServices"/>
</http>
<bean id="rememberMeServices" class=
"org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="myUserDetailsService"/>
<property name="key" value="springRocks"/>
<property name="matchingAlgorithm" value="MD5"/>
<property name="encodingAlgorithm" value="MD5"/>
</bean>
传播AuthenticationServiceException
s
AuthenticationFilter
传播AuthenticationServiceException
s 到AuthenticationEntryPoint
.
因为AuthenticationServiceException
表示服务器端错误而不是客户端错误,在 6.0 中,此更改会将它们传播到容器。
配置AuthenticationFailureHandler
重新抛出AuthenticationServiceException
s
要为 6.0 默认值做准备,请将AuthenticationFilter
具有AuthenticationFailureHandler
那个会重新抛出AuthenticationServiceException
s,如下所示:
-
Java
-
Kotlin
-
Xml
AuthenticationFilter authenticationFilter = new AuthenticationFilter(...);
AuthenticationEntryPointFailureHandler handler = new AuthenticationEntryPointFailureHandler(...);
handler.setRethrowAuthenticationServiceException(true);
authenticationFilter.setAuthenticationFailureHandler(handler);
val authenticationFilter: AuthenticationFilter = new AuthenticationFilter(...)
val handler: AuthenticationEntryPointFailureHandler = new AuthenticationEntryPointFailureHandler(...)
handler.setRethrowAuthenticationServiceException(true)
authenticationFilter.setAuthenticationFailureHandler(handler)
<bean id="authenticationFilter" class="org.springframework.security.web.authentication.AuthenticationFilter">
<!-- ... -->
<property ref="authenticationFailureHandler"/>
</bean>
<bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.AuthenticationEntryPointFailureHandler">
<property name="rethrowAuthenticationServiceException" value="true"/>
</bean>
选择退出步骤
如果重新抛出AuthenticationServiceException
s 给你带来麻烦,你可以将值设置为 false 而不是采用 6.0 的默认值,如下所示:
-
Java
-
Kotlin
-
Xml
AuthenticationFilter authenticationFilter = new AuthenticationFilter(...);
AuthenticationEntryPointFailureHandler handler = new AuthenticationEntryPointFailureHandler(...);
handler.setRethrowAuthenticationServiceException(false);
authenticationFilter.setAuthenticationFailureHandler(handler);
val authenticationFilter: AuthenticationFilter = new AuthenticationFilter(...)
val handler: AuthenticationEntryPointFailureHandler = new AuthenticationEntryPointFailureHandler(...)
handler.setRethrowAuthenticationServiceException(false)
authenticationFilter.setAuthenticationFailureHandler(handler)
<bean id="authenticationFilter" class="org.springframework.security.web.authentication.AuthenticationFilter">
<!-- ... -->
<property ref="authenticationFailureHandler"/>
</bean>
<bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.AuthenticationEntryPointFailureHandler">
<property name="rethrowAuthenticationServiceException" value="false"/>
</bean>