You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 17:27:04