Spring Security中permitAll接口带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
相关产品推荐
相关产品推荐

