Spring Security 6中requestMatcher().permitAll()失效问题求助
问题
使用Spring Security 6实现基础认证时,配置的requestMatcher().permitAll()未生效。已设置放行/register端点,但请求该接口仍返回401未授权状态。
相关代码
SecurityConfig配置
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import static org.springframework.security.config.Customizer.withDefaults; @Configuration @EnableWebSecurity @EnableMethodSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(auth -> auth .requestMatchers(request -> request.getRequestURI().contains("/register")).permitAll() .anyRequest().authenticated()) .httpBasic(withDefaults()) .formLogin(withDefaults()); return http.build(); } @Bean public UserDetailsService userDetailsService(){ return new OurUserInfoUserDetailsService(); } @Bean public AuthenticationProvider authenticationProvider() { DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); daoAuthenticationProvider.setUserDetailsService(userDetailsService()); daoAuthenticationProvider.setPasswordEncoder(passwordEncoder()); return daoAuthenticationProvider; } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
Controller代码
import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @GetMapping("/register") public ResponseEntity reg(){ return ResponseEntity.ok("HELOO"); } }
调试日志(添加logging.level.org.springframework.security=DEBUG后)
2024-03-24T00:52:24.232+07:00 DEBUG 12296 --- [schoolManage] [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Securing GET /register 2024-03-24T00:52:24.248+07:00 DEBUG 12296 --- [schoolManage] [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Secured GET /register 2024-03-24T00:52:24.282+07:00 DEBUG 12296 --- [schoolManage] [nio-8080-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext 2024-03-24T00:52:24.296+07:00 DEBUG 12296 --- [schoolManage] [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Securing GET /error 2024-03-24T00:52:24.297+07:00 DEBUG 12296 --- [schoolManage] [nio-8080-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext 2024-03-24T00:52:24.304+07:00 DEBUG 12296 --- [schoolManage] [nio-8080-exec-2] o.s.s.w.s.HttpSessionRequestCache : Saved request http://localhost:8080/error?continue to session 2024-03-24T00:52:24.314+07:00 DEBUG 12296 --- [schoolManage] [nio-8080-exec-2] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using Or [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest], And [Not [MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@628bf7a9, matchingMediaTypes=[text/html], useEquals=false, ignoredMediaTypes=[]]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@628bf7a9, matchingMediaTypes=[application/atom+xml, application/x-www-form-urlencoded, application/json, application/octet-stream, application/xml, multipart/form-data, text/xml], useEquals=false, ignoredMediaTypes=[*/*]]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@628bf7a9, matchingMediaTypes=[*/*], useEquals=true, ignoredMediaTypes=[]]] 2024-03-24T00:52:24.315+07:00 DEBUG 12296 --- [schoolManage] [nio-8080-exec-2] s.w.a.DelegatingAuthenticationEntryPoint : Match found! Executing org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint@709090f8 2024-03-24T00:52:24.315+07:00 DEBUG 12296 --- [schoolManage] [nio-8080-exec-2] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest] 2024-03-24T00:52:24.316+07:00 DEBUG 12296 --- [schoolManage] [nio-8080-exec-2] s.w.a.DelegatingAuthenticationEntryPoint : No match found. Using default entry point org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint@16b994d5
解决方案
从调试日志可见,/register请求本身已被Spring Security放行,但后续跳转到了/error接口,该接口触发认证校验导致401。问题根源是Controller的reg()方法未指定ResponseEntity泛型类型,Spring MVC处理时出现类型转换异常,进而触发错误页面跳转。
修复步骤
- 修改Controller方法,明确指定
ResponseEntity的泛型类型:
@GetMapping("/register") public ResponseEntity<String> reg(){ return ResponseEntity.ok("HELOO"); }
- 优化SecurityConfig中的请求匹配规则,改用精确匹配避免意外:
.authorizeHttpRequests(auth -> auth .requestMatchers("/register").permitAll() .anyRequest().authenticated())
修改完成后,/register接口即可正常返回响应,不会触发错误页面跳转,401问题也会解决。
内容的提问来源于stack exchange,提问作者blueonline07
相关产品推荐
相关产品推荐

