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

使用Ajax调用Microsoft Graph API获取Access Token时出现403 Forbidden错误,但Postman可正常请求

分析403 Forbidden错误的原因及解决方法

我来帮你排查这个问题,先从几个关键点入手:

核心原因1:请求数据格式与Content-Type不匹配

你的代码里存在一个明显的矛盾点:

  • 你手动设置了请求头content-type: application/x-www-form-urlencoded,这是微软OAuth2令牌端点明确要求的参数格式
  • 但你同时使用了FormData,并且设置了contentType: false和processData: false——这会让浏览器自动将请求的Content-Type设为multipart/form-data,和你手动指定的格式直接冲突

微软的令牌端点不接受multipart/form-data格式的请求,这是触发403错误的主要原因。而Postman里你应该是正确选择了x-www-form-urlencoded类型来发送参数,所以能正常获取令牌。

核心原因2:CORS Anywhere公共实例的访问限制

https://cors-anywhere.herokuapp.com/是一个公共的CORS代理服务,它有请求频率限制,而且现在很多浏览器会拦截未验证的请求——如果你之前没访问过它的主页,可能会被临时限制访问,这也可能导致403错误。


解决方法

方法1:修正请求数据格式,匹配x-www-form-urlencoded要求

把FormData换成URLSearchParams,或者直接拼接成符合格式的字符串,同时调整Ajax参数:

const params = new URLSearchParams();
params.append("client_id", "client_id");
params.append("client_secret", "S7D7Q~excS5KjBh9JnPK-afZjTjtALGTKNweP");
params.append("grant_type", "client_credentials");
params.append("scope", "https://graph.microsoft.com/.default");

$(document).ready(function () {
    requestToken();
});

var token;
function requestToken() {
    $.ajax({
        async: true,
        crossDomain: true,
        // 移除credentials: "include",client credentials flow不需要携带浏览器凭证
        url: "https://cors-anywhere.herokuapp.com/https://login.microsoftonline.com/b262d1f3-4738-400d-ad54-c82cdabb6540/oauth2/v2.0/token",
        method: "POST",
        headers: { "content-type": "application/x-www-form-urlencoded" },
        cache: false,
        // 这里不需要processData和contentType: false,参数格式已经符合要求
        data: params,
        success: function (response) {
            console.log(response);
            token = response.access_token;
        },
        error: function(xhr, status, error) {
            console.log("错误状态:", status);
            console.log("错误信息:", error);
            console.log("响应内容:", xhr.responseText);
        }
    });
}

方法2:解锁CORS Anywhere公共实例的访问权限

如果你继续使用公共的CORS Anywhere实例,先在浏览器中访问它的主页,点击页面上的"Request temporary access to the demo server"按钮,解锁临时访问权限,然后再运行你的Ajax代码。

更稳妥的方案:自己部署一个私有CORS Anywhere实例,避免公共服务的限流和访问限制。

方法3:额外检查点

  • 再次核对client_id和client_secret的拼写(Postman能正常请求的话这个大概率没问题,但还是确认下)
  • 务必移除credentials: "include"——client credentials flow是通过client_id和client_secret验证身份,不需要携带浏览器的Cookie等凭证,这个参数可能会干扰请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 12:54:12