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

Spring4.3+OAuth2跨域问题求助:AJAX请求令牌报CORS错误

解决Spring OAuth2 /oauth/token端点的CORS跨域问题

看起来你遇到的核心问题是:Spring Security OAuth2的/oauth/token端点没有被你的CORS配置覆盖,这个端点属于授权服务器的管辖范围,不在普通的WebMvc或Spring Security过滤链里,所以你之前的配置都没生效。另外你的CORS配置还有一个违反浏览器规范的冲突点,我一步步给你解决:

问题1:CORS配置的Origin与Credentials冲突

你的CorsConfiguration里同时设置了setAllowedOrigins(Arrays.asList("*"))和setAllowCredentials(true),这在浏览器中是不允许的——当请求的credentials模式为include时,Access-Control-Allow-Origin不能是通配符*,必须指定具体的客户端域名。

修正CORS配置Bean

@Bean
public CorsConfigurationSource corsConfigurationSource() {
    final CorsConfiguration configuration = new CorsConfiguration();
    // 替换成你的客户端实际地址(比如你报错里的http://localhost:8080)
    configuration.setAllowedOrigins(Arrays.asList("http://localhost:8080"));
    configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH","OPTIONS"));
    configuration.setAllowCredentials(true);
    configuration.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));
    // 暴露OAuth2响应中可能需要的头信息(可选,但建议加上)
    configuration.setExposedHeaders(Arrays.asList("Authorization"));
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

问题2:/oauth/token端点未被CORS过滤器覆盖

/oauth/token是Spring Security OAuth2授权服务器的核心端点,它的请求处理链独立于普通的Spring Security过滤链,所以你需要在授权服务器的配置中专门添加CORS过滤器。

添加授权服务器配置类

创建一个AuthorizationServerConfig类,把CORS过滤器绑定到token端点:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    private final AuthenticationManager authenticationManager;
    private final CorsConfigurationSource corsConfigurationSource;

    // 构造注入所需Bean
    public AuthorizationServerConfig(AuthenticationManager authenticationManager, CorsConfigurationSource corsConfigurationSource) {
        this.authenticationManager = authenticationManager;
        this.corsConfigurationSource = corsConfigurationSource;
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        // 允许表单方式获取token(适配password模式)
        security.allowFormAuthenticationForClients();
        // 给/oauth/token端点添加CORS过滤器
        security.addTokenEndpointAuthenticationFilter(new CorsFilter(corsConfigurationSource));
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // 这里配置你的客户端信息,要和你AJAX请求中的Basic认证对应
        clients.inMemory()
                .withClient("oauthCrud") // 对应你Authorization头里的b2F1dGhDcnVk(base64解码后的值)
                .secret("oauthSuperSecret") // 对应Authorization头里的om9hdXRoU3VwZXJTZWNyZXQ=
                .authorizedGrantTypes("password", "refresh_token")
                .scopes("read", "write");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // 绑定AuthenticationManager用于密码模式认证
        endpoints.authenticationManager(authenticationManager);
    }
}

修正SecurityConfig,暴露AuthenticationManagerBean

在你的SecurityConfig中添加authenticationManagerBean方法,让授权服务器能获取到认证管理器:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // 暴露AuthenticationManagerBean给授权服务器使用
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    @Order(Ordered.HIGHEST_PRECEDENCE)
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .csrf().disable() // REST API建议禁用CSRF,尤其是OAuth2 password模式
                .authorizeRequests()
                // 批量放行无需认证的端点
                .antMatchers("/register", "/contact", "/signup", "/oauth/**").permitAll()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .httpBasic();
    }
}

调整客户端AJAX请求

添加xhrFields.withCredentials,确保浏览器能正确处理凭证(和服务端的allowCredentials(true)对应):

var settings = {
    "async": true,
    "crossDomain": true,
    "xhrFields": {
        "withCredentials": true
    },
    "url": "http://10.10.1.13:8080/OauthCrud/oauth/token",
    "method": "POST",
    "headers": {
        "authorization": "Basic b2F1dGhDcnVkOm9hdXRoU3VwZXJTZWNyZXQ=",
        "content-type": "application/x-www-form-urlencoded",
        "cache-control": "no-cache"
    },
    "data": {
        "username": "rama",
        "password": "rama",
        "grant_type": "password"
    }
}
$.ajax(settings).done(function (response) {
    console.log(response);
});

验证步骤

  1. 重启服务端应用
  2. 重新发起AJAX请求,检查浏览器控制台是否还存在CORS错误
  3. 如果还有问题,可以查看浏览器的Network面板,检查OPTIONS预请求的响应头是否包含正确的Access-Control-Allow-Origin、Access-Control-Allow-Methods等字段

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:54:11