【问题标题】:Request succeeds on server but results in CORS error in browser请求在服务器上成功,但在浏览器中导致 CORS 错误
【发布时间】:2023-03-20 13:19:01
【问题描述】:

我向 microsoft login 发出 HTTP POST 请求以获取与邮件 API 一起使用的访问令牌,请求成功,但代码转到我代码的错误子句。

requestAccessToken(code: string)
{
console.log("request access token");
if (code) {
  var headers = new Headers();
  headers.append("Content-Type", 'application/x-www-form-urlencoded');
  headers.append('Accept', 'application/json');
  var requestoptions = new RequestOptions({
    headers: headers
  });
  var body = `grant_type=authorization_code&
              redirect_uri=http://localhost:4200&
              code=`+ code + `&
              client_id=4e[................]5ab&
              client_secret=CE[..............]BC`;

  this.http.post("https://login.microsoftonline.com/common/oauth2/v2.0/token", body, requestoptions).map((res: Response) =>
  {
    console.log("response given");
    const data = res.json();
  }).subscribe( (data) => {
     console.log("The data is = " + data); 
  }, error => { 
    console.log("The error is = " + error)
  });
}

浏览器控制台显示如下: XMLHttpRequest 无法加载 https://login.microsoftonline.com/common/oauth2/v2.0/token。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'http://localhost:4200' 不允许访问。 zone.js:2019 XHR 加载失败:POST "https://login.microsoftonline.com/common/oauth2/v2.0/token"。 outlook.service.ts:96 错误是 = 响应状态:0 对于 URL:null

这里有一个截图可以更好地展示它

现在真正的问题是我的请求成功了,如下所示:

并且响应显示我的访问令牌。那么为什么我不能从代码中得到它呢?为什么它会出现错误子句。

【问题讨论】:

  • 这是一个 CORS 问题
  • 你知道这个数字了吗?我在尝试从login.microsoftonline.com/[tenant_id]/oauth2/token获取访问令牌时遇到了同样的错误
  • @hngdev 不。我们不得不强迫用户手动做一些事情。这是因为 CORS 的东西是真正的 PITA

标签: javascript angular typescript http cors


【解决方案1】:

您看到的是向服务器发送跨域请求但未在响应中收到 Access-Control-Allow-Origin 响应标头时的预期行为。

具体来说,只要您的跨域请求没有导致您的浏览器在发出请求之前执行preflight OPTIONS request 的特征,那么该请求将在服务器端成功 - 但是,因为来自服务器的响应该请求不包含 Access-Control-Allow-Origin 响应标头,您的浏览器会阻止您的前端代码实际看到服务器发送的响应。

但是,如果您打开浏览器 devtools,您仍然可以在那里看到响应。但仅仅因为浏览器收到了响应并且您可以在 devtools 中看到它,并不意味着浏览器会将响应公开给您的代码。只有当它有Access-Control-Allow-Origin时才会暴露它。


这一切可能看起来有悖常理,但如果您记得浏览器是实施跨域限制的唯一点,这一切都是有道理的。服务器不会阻止跨域请求。

当您发送请求的服务器接收到请求时,它不会检查来源来决定是否响应。服务器只是接受请求并处理它,然后发送响应。但随后浏览器会阻止您的代码访问该响应。

但同样重要的是要记住,浏览器不会阻止您的代码发送跨域请求。浏览器仅在请求具有触发浏览器执行preflight 的质量(如特殊标头)时阻止发送跨域请求。

因此,如果您的请求不是触发预检的请求,则浏览器会发送它,服务器会接收并处理它。如果请求方法是POST 或其他目的是改变服务器状态的方法——在这种情况下,你可能不太关心响应是什么——那么在某种程度上,请求对服务器端产生了预期的影响,也算是成功了。

但请考虑当您确实非常关心响应是什么时会发生什么:考虑GET 请求会发生什么,其中发出请求的全部目的是获取响应。

如上所述,如果请求不是触发预检的请求,则浏览器发送它,服务器接收它并返回响应。但是,如果响应不包含 Access-Control-Allow-Origin 响应标头,您的浏览器将不会让您的前端 JavaScript 代码访问它。

显然,由于发出GET 请求的全部目的是对响应做一些事情,那么在这种情况下,如果您的代码无法访问响应,那将是一个艰难的、彻底的失败——与POST 请求,其中请求正文实际上仍然按预期发布,但您的代码无法检查响应以查看请求是否成功。

【讨论】:

    【解决方案2】:

    您已经用“cors”正确标记了您的帖子。现代浏览器不允许跨域访问端点,除非端点发送允许您访问它的 cors-headers。

    如果您检查您的网络选项卡,应该有一个 OPTIONS 请求到https://login.microsoftonline.com/common/oauth2/v2.0/token。这称为 preflight-request,它检查 Access-Control-Allow-Origin 和 Access-Control-Allow-Methods 标头。 Access-Control-Allow-Origin 必须包含您的域或 *,并且 Control-Allow-Methods 必须包含 POST 或 *。

    我不熟悉 office api,但我认为必须有一种方法可以将您的应用程序配置为有效端点。也许这篇文章会对你有所帮助:https://msdn.microsoft.com/en-us/office/office365/howto/create-web-apps-using-cors-to-access-files-in-office-365

    【讨论】:

    猜你喜欢
    • 2018-08-07
    • 2021-08-23
    • 2015-03-09
    • 2019-12-11
    • 1970-01-01
    • 2017-06-30
    • 2020-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多