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

Spring Security中permitAll接口带Authorization头访问被拒的解决咨询

解决Spring Security公开API带Authorization头被拒绝的问题

你当前的配置里,permitAll()只是授权阶段允许访问,但如果请求带了Authorization头,Spring Security还是会执行认证流程。要是头里的凭证无效(比如格式错、过期),就会返回401拒绝访问。要让/api/public不管有没有这个头都能正常访问,得让它完全跳过认证流程,或者即使认证失败也放行。

推荐两种解决方案:

方案一:拆分两个SecurityFilterChain(更清晰)

把公开路径和受保护路径分开处理,公开路径的FilterChain不触发任何认证逻辑:

// 专门处理公开API的FilterChain
@Bean
SecurityFilterChain publicApiFilterChain(HttpSecurity http) throws Exception {
    http
        .securityMatcher(HttpMethod.GET, "/api/public")
        .authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
    return http.build();
}

// 处理受保护API的FilterChain
@Bean
SecurityFilterChain protectedApiFilterChain(HttpSecurity http) throws Exception {
    http
        .securityMatcher(HttpMethod.GET, "/api/**")
        .authorizeHttpRequests(auth -> auth
            .requestMatchers(HttpMethod.GET, "/api/public").permitAll()
            .anyRequest().authenticated()
        )
        .httpBasic(Customizer.withDefaults())
        .headers(headers -> headers
            .frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)
            .contentSecurityPolicy(csp -> csp.policyDirectives(
                "default-src 'self'; " +
                "style-src 'self' 'unsafe-inline'; " +
                "script-src 'self'; " +
                "form-action 'self'; " +
                "connect-src 'self'; " +
                "frame-src 'self'; " +
                "frame-ancestors 'self'; " +
                "font-src 'self'; " +
                "media-src 'self'; " +
                "object-src 'self'; " +
                "manifest-src 'self';"
            ))
        );
    return http.build();
}

方案二:在原有FilterChain里添加认证失败兜底处理

如果不想拆分配置,可以自定义认证入口点,当访问/api/public时,即使认证失败也直接放行:

@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -> auth
            .requestMatchers(HttpMethod.GET, "/api/public").permitAll()
            .requestMatchers(HttpMethod.GET, "/api/*").authenticated()
        )
        .httpBasic(Customizer.withDefaults())
        // 自定义认证失败的处理逻辑
        .exceptionHandling(exception -> exception
            .authenticationEntryPoint((request, response, authException) -> {
                // 访问公开API时,不管认证结果如何都返回200
                if ("/api/public".equals(request.getRequestURI())) {
                    response.setStatus(HttpServletResponse.SC_OK);
                } else {
                    // 其他受保护路径按默认返回401
                    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                }
            })
        )
        .headers(headers -> headers
            .frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)
            .contentSecurityPolicy(csp -> csp.policyDirectives(
                "default-src 'self'; " +
                "style-src 'self' 'unsafe-inline'; " +
                "script-src 'self'; " +
                "form-action 'self'; " +
                "connect-src 'self'; " +
                "frame-src 'self'; " +
                "frame-ancestors 'self'; " +
                "font-src 'self'; " +
                "media-src 'self'; " +
                "object-src 'self'; " +
                "manifest-src 'self';"
            ))
        );
    return http.build();
}

方案一更推荐,从根源上避免了公开路径触发认证逻辑;方案二适合快速调整原有配置的场景。

内容的提问来源于stack exchange,提问作者Paolo Mascellani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 02:27:07