Spring Boot 3 Digest Authentication配置失效,请求技术支援
Spring Boot 3 中 Digest Authentication 配置修复方案
你的配置存在两个核心问题,导致认证返回403:
- 用户密码未正确关联NoOpPasswordEncoder:Spring Security 6中
User.builder()默认会使用DelegatingPasswordEncoder加密密码,即使你声明了NoOpPasswordEncoder,若不明确指定,存储的密码会被加密,而Digest认证需要明文密码计算摘要,无法匹配。 - DigestAuthenticationFilter未配置密码编码器:该过滤器需要知道使用哪个编码器获取用户密码,否则无法完成摘要验证逻辑。
修正后的WebSecurityConfig代码
package com.example.springboot3digest.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint; import org.springframework.security.web.authentication.www.DigestAuthenticationFilter; @Configuration @EnableWebSecurity public class WebSecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http, DigestAuthenticationFilter digestAuthenticationFilter) throws Exception { http .authorizeHttpRequests(request -> request.anyRequest().authenticated()) .exceptionHandling(e -> e.authenticationEntryPoint(digestAuthenticationEntryPoint())) .addFilterBefore(digestAuthenticationFilter, BasicAuthenticationFilter.class) .csrf(csrf -> csrf.disable()); // REST API场景建议关闭CSRF return http.build(); } @Bean UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) { UserDetails user = User.builder() .username("user") .password("user") .passwordEncoder(passwordEncoder::encode) // 显式指定密码编码器 .roles("USER") .build(); return new InMemoryUserDetailsManager(user); } @Bean public PasswordEncoder passwordEncoder() { return NoOpPasswordEncoder.getInstance(); } @Bean DigestAuthenticationEntryPoint digestAuthenticationEntryPoint() { DigestAuthenticationEntryPoint entryPoint = new DigestAuthenticationEntryPoint(); entryPoint.setRealmName("My App Realm"); entryPoint.setKey("3028472b-da34-4501-bfd8-a355c42bdf92"); return entryPoint; } @Bean DigestAuthenticationFilter digestAuthenticationFilter(UserDetailsService userDetailsService, DigestAuthenticationEntryPoint entryPoint, PasswordEncoder passwordEncoder) { DigestAuthenticationFilter filter = new DigestAuthenticationFilter(); filter.setUserDetailsService(userDetailsService); filter.setAuthenticationEntryPoint(entryPoint); filter.setUserPasswordEncoder(passwordEncoder); // 配置密码编码器 return filter; } }
关键修改点说明
- 显式关联密码编码器到User构建器:在
userDetailsService方法中,通过.passwordEncoder(passwordEncoder::encode)指定使用NoOpPasswordEncoder,确保密码以明文存储(符合Digest认证的要求)。 - 将Digest相关组件声明为@Bean:让Spring统一管理实例,避免重复创建导致的配置不一致。
- 给DigestAuthenticationFilter设置userPasswordEncoder:让过滤器能正确获取用户的明文密码来验证客户端发送的摘要。
- 关闭CSRF保护:对于无状态的REST API,CSRF保护通常不需要,开启反而会导致请求被拦截。
验证方式
使用curl测试:
curl -v --digest -u user:user http://localhost:8080/
应该能正常返回Hello World!。
内容的提问来源于stack exchange,提问作者Martin Spudich
相关产品推荐
相关产品推荐

