Spring Boot Security中requestMatchers().permitAll()不生效问题排查
Spring Boot Security放行资源仍返回401/403问题排查
问题描述
我在使用Spring Boot Security实现控制器认证时,遇到了一个棘手的问题:明明在自定义SecurityFilterChain里明确放行的资源,访问时还是返回401 Unauthorized或403 Forbidden错误。
我的配置代码如下:
@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .cors() .and() .csrf().disable() .exceptionHandling() .authenticationEntryPoint(unauthorizedHandler) .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeHttpRequests() .requestMatchers("/api/auth/**").permitAll() .requestMatchers("/api/test/**").permitAll() .requestMatchers(h2ConsolePath + "/**").permitAll() .anyRequest().authenticated(); http .headers() .frameOptions().sameOrigin(); http .authenticationProvider(authenticationProvider()); http .addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); }
具体现象:
- 访问h2控制台时,期望无需认证,但实际返回403 Forbidden;
- 新增了不带
@PreAuthorize注解的TestController,访问/api/test/**时收到错误提示:
Full authentication is required to access this resource
- 即使移除
.anyRequest().authenticated();代码行,上述错误依然存在; - 调试时确认程序会进入
filterChain方法,说明配置应该被加载,但过滤器链似乎没生效。
排查方向及解决方法
1. 校验放行路径的正确性
先确认h2ConsolePath变量的实际值是否正确(默认H2控制台路径是/h2-console),可以先硬编码路径测试,排除变量拼接错误的可能:
.requestMatchers("/h2-console/**").permitAll()
2. 检查自定义JWT过滤器的逻辑
你的authenticationJwtTokenFilter()如果没有跳过已放行的路径,即使Security配置里放行了,过滤器仍会强行校验JWT,导致返回401。需要在过滤器里添加路径判断:
@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String requestURI = request.getRequestURI(); // 跳过放行路径的JWT校验 if (requestURI.startsWith("/api/auth/") || requestURI.startsWith("/api/test/") || requestURI.startsWith("/h2-console/")) { filterChain.doFilter(request, response); return; } // 后续JWT校验逻辑... }
3. 排查是否存在多份Security配置
如果项目里有多个@Bean标注的SecurityFilterChain,Spring会按@Order注解的优先级执行,可能存在其他配置覆盖了当前规则。可以给当前配置加上@Order(1)确保优先级最高,或者清理多余的配置类。
4. 验证CORS配置是否冲突
虽然开启了.cors(),但如果自定义了CORS过滤器,可能和Security的CORS配置冲突。可以显式配置CORS规则测试:
http.cors(cors -> cors.configurationSource(request -> { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Arrays.asList("*")); config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); config.setAllowedHeaders(Arrays.asList("*")); return config; }))
5. 确认H2控制台的特殊配置
H2控制台除了路径放行,还需要确保:
application.properties中开启控制台:spring.h2.console.enabled=true- 确认
.headers().frameOptions().sameOrigin()配置生效,避免iframe加载被拦截导致403
6. 避免过滤器重复注册
Spring Boot可能会自动注册自定义过滤器,导致过滤器执行两次或顺序错误。可以通过以下方式让Security单独管理过滤器:
@Bean public FilterRegistrationBean<AuthenticationJwtTokenFilter> registerJwtFilter(AuthenticationJwtTokenFilter filter) { FilterRegistrationBean<AuthenticationJwtTokenFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(filter); registrationBean.setEnabled(false); // 禁用Spring Boot自动注册 return registrationBean; }
内容的提问来源于stack exchange,提问作者Sandro
相关产品推荐
相关产品推荐

