Digest Authentication

本部分详细介绍了 Spring Security 如何提供 Digest AuthenticationDigestAuthenticationFilter 提供了 Digest Authentication

This section provides details on how Spring Security provides support for Digest Authentication, which is provided DigestAuthenticationFilter.

你不应在现代应用程序中使用摘要认证,因为它不被认为是安全的。最明显的问题是,你必须将密码存储为纯文本或加密或 MD5 格式。所有这些存储格式都被认为是不安全的。相反,你应使用单向自适应密码哈希(bCrypt、PBKDF2、SCrypt 等)来存储凭据,而摘要认证不支持此方式。

You should not use Digest Authentication in modern applications, because it is not considered to be secure. The most obvious problem is that you must store your passwords in plaintext or an encrypted or MD5 format. All of these storage formats are considered insecure. Instead, you should store credentials by using a one way adaptive password hash (bCrypt, PBKDF2, SCrypt, and others), which is not supported by Digest Authentication.

摘要身份验证尝试解决 Basic authentication 的许多弱点,具体而言,通过确保证书从不会以明文形式通过网络发送。许多 browsers support Digest Authentication

Digest Authentication tries to solve many of the weaknesses of Basic authentication, specifically by ensuring credentials are never sent in clear text across the wire. Many browsers support Digest Authentication.

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

The standard governing HTTP Digest Authentication is defined by RFC 2617, which updates an earlier version of the Digest Authentication standard prescribed by RFC 2069. Most user agents implement RFC 2617. Spring Security’s Digest Authentication support is compatible with the “auth” quality of protection (qop) prescribed by RFC 2617, which also provides backward compatibility with RFC 2069. Digest Authentication was seen as a more attractive option if you need to use unencrypted HTTP (no TLS or HTTPS) and wish to maximize security of the authentication process. However, everyone should use HTTPS.

摘要认证的核心是一个 “nonce”。这是服务器生成的一个值。Spring Security 的随机数遵循以下格式:

Central to Digest Authentication is a “nonce”. This is a value the server generates. Spring Security’s nonce adopts the following format:

Digest Syntax
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 对不安全的纯文本 Password Storage 进行 configure。(请参阅 JavaDoc 中的 {security-api-url}org/springframework/security/crypto/password/NoOpPasswordEncoder.html[NoOpPasswordEncoder] 类。)以下提供使用 Java 配置配置摘要身份验证的示例:

You need to ensure that you configure insecure plain text Password Storage using NoOpPasswordEncoder. (See the {security-api-url}org/springframework/security/crypto/password/NoOpPasswordEncoder.html[NoOpPasswordEncoder] class in the Javadoc.) The following provides an example of configuring Digest Authentication with Java Configuration:

Digest Authentication
  • Java

  • XML

@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>