jquery $.ajax 在 Chrome 或 Firefox 中调用会导致 401 未经授权的响应,但在 IE 中有效

Posted

技术标签:

【中文标题】jquery $.ajax 在 Chrome 或 Firefox 中调用会导致 401 未经授权的响应,但在 IE 中有效【英文标题】:jquery $.ajax call results in 401 unauthorized response when in Chrome or Firefox, but works in IE 【发布时间】:2015-06-29 04:55:40 【问题描述】:

我有一个在网页上运行的脚本,它需要使用 JQuery $.ajax 方法(当前使用 jquery 1.7.2)向不同域上的服务端点提交多个 GET 请求。我在 IE (9, 10, 11) 中有 ajax 调用,但它在 Firefox 和 Chrome 中出现 401 Unauthorized 响应而失败。 Chrome 中的部分附加错误消息是“访问此资源需要完全身份验证”。

我的 ajax 调用是这样设置的(对于这些失败的请求,dataType 是“json”,并且 async 是 true):

    $.ajax(
      url: url,
      type: "GET",
      async: isAsync,
      dataType: dataType,
      username: user,
      password: pswd,
      success: function (response, status) 
         // success code here
      ,
      failure: function (response, status) 
         // failure code here
      ,
      complete: function (xhr, status) 
         // on complete code here
      
   );

我正在传递访问服务所需的用户名和密码,这在 IE 中有效。我理解 JQuery ajax 函数将正确处理身份验证,因此如果返回指示需要授权的响应,它将使用提供的凭据来正确发出该请求。我在这里错过了什么吗?我是否需要手动添加 Authorization 标头才能使其正常工作?

更新: 下面是 Chrome 和 IE 通过 F12 调试工具报告的请求、响应和 cookie 信息(部分信息替换为 [...removed...])

铬(42.0.2311.90 m)

响应标头

访问控制允许凭据:true 访问控制允许来源:[...删除...] 访问控制公开标头: 缓存控制:私有,最大年龄=0,必须重新验证连接:保持活动状态 内容编码:gzip 内容长度:296 内容类型:文本/html;字符集=ISO-8859-1 日期:2015 年 4 月 21 日,星期二 格林威治标准时间 20:55:12 到期:2015 年 4 月 21 日星期二 20:55:12 GMT p3p:CP="NON DSP COR CURa PSAa PSDa OUR NOR BUS PUR COM NAV STA" set-cookie:JSESSIONID=qd-app-1348vf1vrksvc76oshcwirvjp.qd-app-13;Path=/;Secure;HttpOnly 设置cookie:NSC_vt1.sbmmzefw.dpn!-!IUUQT=ffffffff09091c3945525d5f4f58455e445a4a42378b;path=/;secure;httponly 状态:401 未经授权的变化:接受编码版本:HTTP/1.1 www-authenticate:Basic realm="Rally ALM"

请求标头

:host:rally1.rallydev.com :method:GET :path:[...removed...] :scheme:https :version:HTTP/1.1 接受:application/json, 文本/javascript, /; q=0.01 接受编码:gzip、放气、sdch 接受语言:en-US,en;q=0.8 来源:[...删除...] referer:[...removed...] user-agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36(KHTML,如 Gecko)Chrome/42.0.2311.90 Safari/537.36

响应 Cookies

JSESSIONID qd-app-1348vf1vrksvc76oshcwirvjp.qd-app-13 NSC_vt1.sbmmzefw.dpn!-!IUUQT ffffffff09091c3945525d5f4f58455e445a4a42378b

IE 11

请求标头

请求 GET [...removed...] 引用 [...removed...] 接受 应用程序/json,文本/javascript,/; q=0.01 Accept-Language en-US 接受编码 gzip,放气用户代理 Mozilla/5.0 (Windows NT 6.1;哇64;三叉戟/7.0; rv:11.0) like Gecko Host [...removed...] Connection Keep-Alive Cache-Control no-cache Cookie JSESSIONID=qd-app-08xmftgye78tde1b0wzcl2kit4m.qd-app-08; NSC_vt1.sbmmzefw.dpn!-!IUUQT=ffffffff09091c3145525d5f4f58455e445a4a42378b; RALLY-Detail-treeCollapsed=false; ZSESSIONID=RpKo5acfRqmjPhW0vIU1rgurWmDhlka0lrGCY9MIWhU; SUBBUCKETID=713

响应标头

响应 HTTP/1.1 200 OK RallyRequestID qd-app-08xmftgye78tde1b0wzcl2kit4m.qd-app-0810353108 周四到期,01 1970 年 1 月 00:00:00 GMT 内容类型文本/javascript;字符集=utf-8 ETag "0101c2c8d3463ee3c1a4f950d4142b7d3" P3P CP="NON DSP COR CURa PSAa PSDa OUR NOR BUS PUR COM NAV STA" 缓存控制 private,max-age=0,must-revalidate 日期 2015 年 4 月 21 日星期二 20:58:17 GMT Connection keep-alive Set-Cookie ZSESSIONID=RpKo5acfRqmjPhW0vIU1rgurWmDhlka0lrGCY9MIWhU;Path=/;Domain=[...removed...];Secure;HttpOnly 设置Cookie SUBBUCKETID=713;Path=/;Domain=[...removed...];Secure;HttpOnly 内容长度 319

Cookie

发送 JSESSIONID qd-app-08xmftgye78tde1b0wzcl2kit4m.qd-app-08 发送 NSC_vt1.sbmmzefw.dpn!-!IUUQT ffffffff09091c3145525d5f4f58455e445a4a42378b 已发送 RALLY-Detail-treeCollapsed false 已发送 ZSESSIONID RpKo5acfRqmjPhW0vIU1rgurWmDhlka0lrGCY9MIWhU 已发送 SUBBUCKETID 713 收到 ZSESSIONID RpKo5acfRqmjPhW0vIU1rgurWmDhlka0lrGCY9MIWhU 在会话结束时 [...删除...] / 是 是 收到 SUBBUCKETID 713 在结束时 会话 [...删除...] / 是的

【问题讨论】:

您是否尝试使用 chrome 或 firefox 中的开发者工具进行调试? 查看网络流量并查看您收到的请求和响应类型 剖析请求和响应,看看是否有任何与 ie 不同的地方。 401 通常由服务器返回。您是否针对远程域进行身份验证(使用 cookie、HTTP 身份验证或其他方式?)。您的浏览器可能不会在所有情况下都发送所需的身份验证。 是的,我是在IE和Chrome的调试工具中。检查网络流量,我看到两者之间存在一些差异,在 IE 中看起来有一个会话 cookie 作为请求的一部分被添加,我猜这是由 JQuery ajax 处理的,因为我正在做是您在原始帖子中的代码示例中看到的内容。另一个区别是,在 Chrome 中,有一个额外的响应头返回:www-authenticate:Basic realm="Rally ALM"。同样,我希望 $.ajax() 函数正在为 IE 处理这个问题,那么 Chrome 和 Firefox 中的问题是什么? 我认为这可能是相关的(特别是关于 Chrome 对何时包含 cookie 进行更严格限制的部分):***.com/questions/2870371/… 【参考方案1】:

我遇到了一个jquery forum post,其中包含有关此问题的一些其他信息。根据我在那里找到的内容,我将其添加到 $.ajax 调用中:

  beforeSend: function (xhr) 
     xhr.setRequestHeader('Authorization', makeBaseAuth(user, pswd));
  

makeBaseAuth() 使用 btoa() 函数的地方如下:

   makeBaseAuth: function(user, pswd) 
      var token = user + ':' + pswd;
      var hash = "";
      if (btoa) 
         hash = btoa(token);
      
      return "Basic " + hash;
   

这似乎现在在 Chrome 中工作,我没有收到登录提示或 401 响应,请求正在通过,我得到了预期的响应。我还删除了选项xhrFields: withCredentials: true ,因为这似乎没有必要。出于某种原因,这在 Firefox 中还不起作用,在 Firefox 调试器中,我实际上无法使用 javascript 进行任何体面的调试以查看问题所在,该脚本的工作方式是将其加载到网页中作为一个匿名脚本,我对此没有任何控制权。我有办法在 IE 和 Chrome 中获取脚本,但由于某种原因不能在 Firefox 中获取。我会认为这只是让它在 Chrome 中工作的胜利,感谢大家在正确的方向上推动我!

【讨论】:

以上是关于jquery $.ajax 在 Chrome 或 Firefox 中调用会导致 401 未经授权的响应,但在 IE 中有效的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个 jQuery AJAX PUT 可以在 Chrome 中工作,但不能在 FF 中工作

在chrome更新后,jQuery ajax调用无法从网页解码到utf-8字符集到Chrome扩展

Chrome 中 JQuery 停止和挂起的 ajax 请求

chrome中的跨域ajax POST

可以在页面加载后拦截 ajax 加载的 HTML/数据的 Google Chrome 扩展

jQuery Ajax 在 IE 6/7/8 中不工作,在 FF/Safari/Chrome 中工作