此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Security 6.4.1spring-doc.cadn.net.cn

摘要式身份验证

本节详细介绍了 Spring Security 如何为摘要式身份验证提供支持,该支持已提供DigestAuthenticationFilter.spring-doc.cadn.net.cn

您不应在现代应用程序中使用 Digest Authentication,因为它不被认为是安全的。 最明显的问题是您必须以明文或加密或 MD5 格式存储密码。 所有这些存储格式都被视为不安全。 相反,您应该使用单向自适应密码哈希(bCrypt、PBKDF2、SCrypt 等)来存储凭证,摘要式身份验证不支持这种哈希值。spring-doc.cadn.net.cn

摘要式身份验证尝试解决基本身份验证的许多弱点,特别是通过确保凭据永远不会以明文形式通过网络发送。 许多浏览器都支持 Digest Authenticationspring-doc.cadn.net.cn

管理 HTTP 摘要式身份验证的标准由 RFC 2617 定义,它更新了 RFC 2069 规定的摘要式身份验证标准的早期版本。 大多数用户代理实现 RFC 2617。 Spring Security 的摘要身份验证支持与“auth”保护质量(qop),RFC 2617 规定,它还提供与 RFC 2069 的向后兼容性。 如果您需要使用未加密的 HTTP(无 TLS 或 HTTPS)并希望最大限度地提高身份验证过程的安全性,则摘要式身份验证被视为更具吸引力的选择。 但是,每个人都应该使用 HTTPSspring-doc.cadn.net.cn

摘要式身份验证的核心是 “nonce”。 这是服务器生成的值。 Spring Security 的 nonce 采用以下格式:spring-doc.cadn.net.cn

摘要语法
base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
expirationTime:   The date and time when the nonce expires, expressed in milliseconds
key:              A private key to prevent modification of the nonce token

您需要确保使用 NoOpPasswordEncoder. (请参阅NoOpPasswordEncoder类。 下面提供了使用 Java 配置摘要式身份验证的示例:spring-doc.cadn.net.cn

摘要式身份验证
@Autowired
UserDetailsService userDetailsService;

DigestAuthenticationEntryPoint entryPoint() {
	DigestAuthenticationEntryPoint result = new DigestAuthenticationEntryPoint();
	result.setRealmName("My App Realm");
	result.setKey("3028472b-da34-4501-bfd8-a355c42bdf92");
}

DigestAuthenticationFilter digestAuthenticationFilter() {
	DigestAuthenticationFilter result = new DigestAuthenticationFilter();
	result.setUserDetailsService(userDetailsService);
	result.setAuthenticationEntryPoint(entryPoint());
}

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
	http
		// ...
		.exceptionHandling(e -> e.authenticationEntryPoint(authenticationEntryPoint()))
		.addFilterBefore(digestFilter());
	return http.build();
}
<b:bean id="digestFilter"
        class="org.springframework.security.web.authentication.www.DigestAuthenticationFilter"
    p:userDetailsService-ref="jdbcDaoImpl"
    p:authenticationEntryPoint-ref="digestEntryPoint"
/>

<b:bean id="digestEntryPoint"
        class="org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint"
    p:realmName="My App Realm"
	p:key="3028472b-da34-4501-bfd8-a355c42bdf92"
/>

<http>
	<!-- ... -->
	<custom-filter ref="userFilter" position="DIGEST_AUTH_FILTER"/>
</http>