摘要认证

本部分详细介绍了 Spring Security 如何提供对 摘要认证 的支持,该认证由 DigestAuthenticationFilter 提供。

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

摘要认证试图解决 基本认证 的许多弱点,具体来说是确保凭据永远不会以明文形式通过网络发送。许多 浏览器支持摘要认证

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

Digest 身份验证的核心是一个“随机数”。这是服务器生成的一个值。Spring Security 的随机数采用以下格式

Digest 语法
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 配置 不安全的纯文本 密码存储。(请参阅 Javadoc 中的 NoOpPasswordEncoder 类。)以下提供了一个使用 Java 配置配置 Digest 身份验证的示例

摘要认证
  • Java

  • XML

@Autowired
UserDetailsService userDetailsService;

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

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

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
	http
		// ...
		.exceptionHandling(e -> e.authenticationEntryPoint(authenticationEntryPoint()))
		.addFilter(digestAuthenticationFilter());
	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>