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

Spring Security登出端点无法从前端访问:跨域问题排查

问题

使用Java 17、Spring Boot 3.0.5和Angular 15开发项目,已配置CORS与安全过滤器,但前端(localhost:4200)调用/auth/api/logout登出接口时出现跨域错误,其他接口均可正常访问。相关配置如下:

CORS配置类

@Configuration
@EnableWebMvc
@RequiredArgsConstructor
public class CorsConfig implements WebMvcConfigurer {

    private final WebConfigPropertiesProvider propertiesProvider;
    @Override
    public void addCorsMappings(@Nonnull CorsRegistry registry) {

        registry.addMapping(propertiesProvider.getConfig().mapping())
                .allowedOriginPatterns(propertiesProvider.getConfig().allowedCorsOrigins())
                .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "PATCH", "OPTIONS")
                .allowCredentials(true);
    }
}

配置属性(已正确加载)

spring.security.web.config.allowed-cors-origins=http://localhost*
spring.security.web.config.mapping=/**

安全过滤器链配置

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
class SecurityConfig {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    private final AuthenticationProvider authenticationProvider;

    private final LogoutService logoutService;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {


        http.cors().and().csrf().disable().authorizeHttpRequests()
                .requestMatchers("/auth/api/**").permitAll()
                .anyRequest().authenticated().
                and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authenticationProvider(authenticationProvider)
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                .exceptionHandling().authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)).and()
                .logout().logoutUrl("/auth/api/logout").addLogoutHandler(logoutService)
                .logoutSuccessHandler((request, response, authentication) -> SecurityContextHolder.clearContext());

        return http.build();
    }
}

登出服务实现

@Service
@RequiredArgsConstructor
public class LogoutService implements LogoutHandler {

    private final TokenRepository tokenRepository;

    @Override
    public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
        final var authHeader = request.getHeader("Authorization");
        final String jwt;
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            return;
        }
        jwt = authHeader.substring(7);
        tokenRepository.findByToken(jwt).
                ifPresent(storedToken -> tokenRepository.deleteTokenByToken(storedToken.getToken()));
    }
}

可能原因分析

  • Spring Security的CORS配置优先级冲突
    Spring Security的http.cors()默认优先使用自身的CORS配置逻辑,而非WebMvcConfigurer中定义的规则。你当前通过WebMvcConfigurer实现的CORS配置,可能没有被Spring Security的过滤器链正确应用到/auth/api/logout接口,导致该接口的跨域请求被拦截。

  • Logout接口的请求方法不匹配
    Spring Security的logout()默认仅支持GET请求,但前端调用登出接口时可能使用了POST方法。即使CORS配置允许POST方法,若Spring Security的logout端点未配置接受POST请求,会导致实际请求或预检请求被拦截,触发跨域错误。

  • 预检OPTIONS请求被过滤器拦截
    虽然CORS配置允许OPTIONS方法,但JwtAuthenticationFilter可能拦截了OPTIONS请求。OPTIONS预检请求不需要携带Authorization Token,过滤器会因Token缺失返回未授权,浏览器会将这类错误判定为跨域问题。

  • AllowedOriginPatterns匹配不精确
    配置中的http://localhost*模式可能无法正确匹配http://localhost:4200。Spring Boot 3对allowedOriginPatterns的匹配规则有严格要求,模糊的localhost*可能无法覆盖带端口的localhost地址,导致跨域校验失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 20:05:27