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

Spring Authorization Server 1.0.0:请求/oauth2/token遇JavaScript跨域错误

解决Spring Authorization Server的CORS与Access Denied问题

问题分析

你遇到的核心矛盾是:浏览器发起/oauth2/token请求时会触发CORS预检(OPTIONS)请求,而Spring Security拦截了该匿名预检请求并返回Access Denied,导致CORS验证失败;但Postman无需发送预检请求,且能正确传递客户端凭证,因此可以正常获取令牌。

解决方案

1. 配置Spring Security允许CORS及预检请求

在Spring Security配置中,需优先启用CORS支持,明确允许前端源、必要HTTP方法(含OPTIONS)和请求头,同时放开预检请求的权限:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            // 先配置CORS,优先级高于权限控制
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
            .authorizeHttpRequests(auth -> auth
                // 允许OPTIONS请求直接通过,无需认证
                .requestMatchers(HttpMethod.OPTIONS, "/oauth2/token").permitAll()
                // 其他请求需认证
                .anyRequest().authenticated()
            )
            // 保留原有授权服务器与资源服务器配置
            .oauth2AuthorizationServer(OAuth2AuthorizationServerConfigurer::authorizationServer)
            .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
            
        return http.build();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration corsConfig = new CorsConfiguration();
        // 允许你的Vue应用源
        corsConfig.setAllowedOrigins(Collections.singletonList("http://127.0.0.1:9010"));
        // 允许必要的HTTP方法,含预检的OPTIONS
        corsConfig.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS"));
        // 允许请求中携带的头信息
        corsConfig.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
        // 允许携带跨域凭证
        corsConfig.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        // 对所有接口应用CORS配置
        source.registerCorsConfiguration("/**", corsConfig);
        return source;
    }
}

2. 调整客户端类型与授权流程

如果你的客户端是confidential类型(需客户端密钥),前端SPA无法安全存储密钥,直接请求/oauth2/token存在安全风险,且浏览器可能因跨域限制无法正确传递Basic Auth凭证。建议:

  • 将客户端改为public类型,结合PKCE授权码流程(Spring Authorization Server默认支持PKCE)
  • 或通过后端代理转发/oauth2/token请求,由后端处理客户端凭证

3. 验证预检请求状态

修改配置后重启服务器,在浏览器控制台查看OPTIONS请求的响应状态码,若返回200则预检通过,后续POST请求即可正常发送。

关键原因说明

  • 浏览器跨域请求会先发送OPTIONS预检请求,该请求不携带任何认证信息(处于匿名状态),Spring Security默认拦截未认证请求,因此返回Access Denied
  • Postman不会触发CORS预检,直接发送POST请求并传递客户端凭证(如Basic Auth),因此能正常获取令牌

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 07:29:58