【问题标题】:XHR POST Cannot send credentials and headerXHR POST 无法发送凭据和标头
【发布时间】:2017-03-02 17:06:20
【问题描述】:

我遇到了一个奇怪的问题,希望有一个非常简单的解决方案。我正在尝试向服务器发送 POST 请求。我已经尝试过使用 fetch 和使用 XMLHttpRequest ,但没有成功。我的 xhr 请求如下所示:

var xhr = new XMLHttpRequest();
xhr.open("POST", location);
xhr.withCredentials = true;
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(obj));

我的获取请求如下所示:

fetch(location, {
      credentials: 'include',
      method: 'post',
      body: JSON.stringify({obj}),
      headers: {
        'Content-Type': 'application/json'
    })
    .then((response) => {
      if (response.ok){
        response = response.json();
      } else {
        response = {};
      }
      window.console.debug(response);
    })
    .then((json) =>{
      window.console.debug(json);
    })
    .catch((error) => {
      window.console.debug(error);
    });

两者的结果相同。如果我像上面那样保留它,则不会发送凭据,因此它会发送一个 OPTIONS 请求,我会收到一个 401。我的 Chrome 网络选项卡请求标头的消息如下所示:

Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:192.168.146.101:8005
Origin:http://localhost:8555
Referer:http://localhost:8555/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36

如果我删除标题行,内容类型是错误的类型(显然),所以我得到一个 415。chrome 网络选项卡请求标题消息如下所示:

Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Authorization:Basic YWRtaW46YWRtaW4=
Connection:keep-alive
Content-Length:504
Content-Type:text/plain;charset=UTF-8
Host:192.168.146.101:8005
Origin:http://localhost:8555
Referer:http://localhost:8555/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36

由于某种原因,当我添加标题时,它会删除凭据。我已经尝试发送编码的用户:像这样在标头中传递(但显然使用真实的用户名/密码):

var xhr = new XMLHttpRequest();
xhr.open("POST", location);
xhr.withCredentials = true;
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Authorization', 'Basic ' + window.btoa('user:pass');
xhr.send(JSON.stringify(obj));

这发生在所有浏览器中。 感谢您的所有帮助!

【问题讨论】:

  • 我想我的问题确实是这样的:如何更改内容类型而不显示在 Access-Control-Request-Headers 下,而只显示默认显示 Content-Type 的位置? Postman 插件能够以某种方式让它显示出来,这似乎是解决这个问题的唯一方法。

标签: javascript rest web xmlhttprequest fetch


【解决方案1】:

withCredentials 属性仅指示是否应使用凭据进行跨站点访问控制请求,我不确定这是否是您要查找的内容 https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials

你试过了吗?

var xhr = new XMLHttpRequest();
xhr.open("POST", location);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Authorization', 'Basic ' + btoa(user+':'+pass);
xhr.send(JSON.stringify(obj));

【讨论】:

  • 在我原来的帖子中我说过我确实尝试了你所说的但它不起作用。我相信 withCredentials 实际上应该提取您的 cookie。
  • 另外,如果你说的是正确的,那么如果没有内容类型,凭据将无法使用,但它们可以。
  • 你说同时使用 withCredentials 和 Authorization 标头,这里的代码似乎很好 jsfiddle.net/y0wwbw6k
  • 如果您注意到,当您通过 setRequestHeader 传入它时,它会以不同的方式传入。它位于 Access-Request-Control-Headers 下。这会导致身份验证失败,因为它不仅仅是在授权下,如果您只使用 withCredentials 而根本不使用 setRequestHeader,这就是去处。当然,我需要 setRequestHeader(或其他设置内容类型的方式)来更改内容类型,这是我的整个问题开始的地方,因为它删除了授权标签。
  • 仅供参考,您不需要自己设置 Authorization 标头。您可以在.open() 方法中执行此操作:xhr.open('POST', location, true, user, pass)
【解决方案2】:

我相信我已经发现了这个问题。问题实际上是响应 REST API 的服务器设置为验证通过的所有内容,包括 OPTIONS 请求。 OPTIONS 请求仅在我们尝试跨域时创建,我就是这样做的。浏览器似乎从 OPTIONS 请求中剥离了身份验证,并且由于我尝试访问的服务器对 OPTIONS 请求进行身份验证(出于某种未知原因),因此它失败了。因此,我现在尝试对我的代码进行 WAR'ing 并将其托管在同一台服务器上,这样我就能解决身份验证问题。

【讨论】:

  • 这对我来说是一个非常棘手的问题。感谢您的回复!
猜你喜欢
  • 1970-01-01
  • 2016-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
  • 1970-01-01
  • 2012-03-09
相关资源
最近更新 更多