POST在服务器上成功但在浏览器中导致CORS错误

Wou*_*tte 6 javascript http cors typescript angular

我对微软登录进行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)
  });
}
Run Code Online (Sandbox Code Playgroud)

浏览器控制台显示:XMLHttpRequest无法加载https://login.microsoftonline.com/common/oauth2/v2.0/token.请求的资源上不存在"Access-Control-Allow-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

这是一个截图,以更好地展示它 控制台错误日志

现在真正的问题是我的请求成功如下所示: 浏览器的网络选项卡

并且响应显示了我的访问令牌.那么为什么我不能从代码中获取它呢?为什么它会出现错误条款.

sid*_*ker 16

当您将跨源发送POST到不在Access-Control-Allow-Origin响应中包含响应头的服务器时,您所看到的是预期的行为.

具体来说,只要您的跨源请求没有任何特性会导致您的浏览器在执行请求之前执行预检OPTIONSPOST请求(您的请求没有),那么POST请求将在服务器端成功 - 但是,因为响应从服务器到该POST请求不包括Access-Control-Allow-Origin响应头,您的浏览器阻止您的前端代码实际上看到服务器发送的响应.

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


这一切似乎都是违反直觉的,但如果你记得浏览器是强制执行跨源限制的唯一点,那一切都是有道理的.服务器不会阻止跨源请求.

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

但同样重要的是要记住,浏览器不会阻止您的代码发送POST请求跨源.当请求具有触发浏览器进行预检的质量(如特殊标题)时,浏览器仅阻止发送跨源请求.

因此,由于您的POST请求不是触发预检的请求,因此浏览器会发送它并成功.

为了便于比较,请考虑跨源GET请求会发生什么.在这种情况下,只要GET请求不是触发预检的那个,浏览器就不会拒绝发送它来跨越原点.相反,浏览器将请求发送到服务器,无论如何.服务器接收该GET请求并发送响应.

只有当响应返回到浏览器时才会发生不同的事情 - 因为在这种情况下,如果响应不包含Access-Control-Allow-Origin响应头,那么您的浏览器将不允许您的前端JavaScript代码访问它.

但很明显,因为提出GET请求的整个过程就是对响应做一些事情,那么在这种情况下,如果你的代码无法访问响应,那就是一个很难的完全失败 - 与POST请求的情况相反,请求正文实际上仍然按预期发布,但您只是没有办法让您的代码检查响应以查看请求是否成功.