为啥 jQuery 的 .ajax() 方法不发送我的会话 cookie?

Posted

技术标签:

【中文标题】为啥 jQuery 的 .ajax() 方法不发送我的会话 cookie?【英文标题】:Why is jQuery's .ajax() method not sending my session cookie?为什么 jQuery 的 .ajax() 方法不发送我的会话 cookie? 【发布时间】:2011-02-21 15:48:20 【问题描述】:

通过$.ajax() 登录到站点后,我尝试向该站点发送第二个$.ajax() 请求 - 但是当我检查使用 FireBug 发送的标头时,请求中没有包含会话 cookie。

我做错了什么?

【问题讨论】:

ajax 的 cookie 可能会出现在 web cookie 之后,而 FireBug 可能会捕获第一页 cookie。 我没有明白你的意思,但我可以说如果我将请求 url 粘贴到浏览器地址栏中并再次检查 Firebug,我可以看到发送到服务器的 headers 中的 cookie。有什么解决办法吗? 所以,我认为 ajax 也会以与浏览器相同的方式处理 你使用的代码是什么? 浏览器仍会在 ajax 请求、jquery 或其他方式期间创建由服务器设置的 cookie。您是否检查了对 ajax 请求的响应并确保从服务器返回要设置的 cookie?服务器代码可能存在问题,甚至没有设置 cookie 等。 【参考方案1】:

我在跨域场景中操作。在登录期间,远程服务器返回 Set-Cookie 标头以及 Access-Control-Allow-Credentials 设置为 true。

下一次对远程服务器的 ajax 调用应该使用这个 cookie。

CORS 的Access-Control-Allow-Credentials 允许跨域日志记录。查看https://developer.mozilla.org/En/HTTP_access_control 获取示例。

对我来说,这似乎是 JQuery 中的一个错误(或者至少是下一个版本中的功能)。

更新:

    不会从 AJAX 响应自动设置 Cookie(引用:http://aleembawany.com/2006/11/14/anatomy-of-a-well-designed-ajax-login-experience/)

    为什么?

    您无法从响应中获取 cookie 的值来手动设置它 (http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-getresponseheader)

    我很困惑..

    应该有办法让jquery.ajax()设置XMLHttpRequest.withCredentials = "true"参数。

回答: 您应该使用http://api.jquery.com/jQuery.ajax/ 的xhrFields 参数

文档中的例子是:

$.ajax(
   url: a_cross_domain_url,
   xhrFields: 
      withCredentials: true
   
);

服务器正确响应此请求也很重要。在这里复制来自@Frédéric 和@Pebbl 的优秀cmets:

Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding. The above example would fail if the header was wildcarded as: Access-Control-Allow-Origin: *

所以当请求是:

Origin: http://foo.example
Cookie: pageAccess=2

服务器应该响应:

Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Credentials: true

[payload]

否则负载将不会返回到脚本。见:https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials

【讨论】:

太棒了!我添加使用这个 + 在服务器端将 Access-Control-Allow-Credentials 标头设置为 true 我在哪里设置这些凭据?在 Header Autorization 中?在请求正文中? 感谢您的回答 :) 只是一个快速补充,可能值得一提 Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding. The above example would fail if the header was wildcarded as: Access-Control-Allow-Origin: * developer.mozilla.org/en-US/docs/Web/HTTP/… 不幸的是,这些都不适合我。如果我从 AngularJS 运行相同的请求,它可以工作,但从 jQuery 运行,即使有这些建议,会话 Cookie 也不会传递。 (jQuery v2.1.1) (O.O) 你把我从各种痛苦的时刻中解救了出来。多么完美的答案!谢谢!我需要在我的网站的公共根 .htaccess 中添加这些: Header set Access-Control-Allow-Origin "localhost" Header set Access-Control-Allow-Credentials "true" 【参考方案2】:

AJAX 调用仅在您调用的 url 与调用脚本位于同一域时发送 Cookie。

这可能是一个跨域问题。

也许您在调用脚本位于 www.domain-b.com 时尝试从 www.domain-a.com 调用 url(换句话说:您进行了跨域调用,在这种情况下浏览器不会发送任何 cookie 以保护您的隐私) .

在这种情况下,您的选择是:

编写一个驻留在域-b 上的小型代理,并将您的请求转发到域-a。您的浏览器将允许您调用代理,因为它与调用脚本位于同一台服务器上。然后您可以配置此代理以接受它可以发送到域-a 的 cookie 名称和值参数。但要使此功能起作用,您需要知道 cookie 的名称并在域中为您的服务器赋值 - 需要进行身份验证。 如果您要获取 JSON 对象,请尝试改用 JSONP 请求。 jQuery 支持这些。但是您需要更改 domain-a 上的服务,以便它返回有效的 JSONP 响应。

很高兴这能帮上一点忙。

【讨论】:

另外值得注意的是,cookie 可以设置为特定路径,因此如果您使用path=/something 设置cookie,并且您正在请求页面/another,则不会发送cookie。当您请求页面/something 时,cookie 将按预期发送。因此,请检查设置 cookie 的代码。 jsonp 请求会发送 cookie 吗? @albanx 是的,如果设置了我提到的要求。这只是一个正常的请求,就像其他任何请求一样,因此会发送 cookie。 @albanx 这个other related question 包含一个如何使用自定义 cookie 执行 JSONP 请求的示例 根据 Wikipedia 上的 JSONP > 这种方法被放弃了,转而使用 CORS【参考方案3】:

使用

xhrFields:  withCredentials:true 

作为我的 jQuery ajax 调用的一部分只是解决方案的一部分。我还需要在我的资源的 OPTIONS 响应中返回标头:

Access-Control-Allow-Origin : http://www.wombling.com
Access-Control-Allow-Credentials : true

重要的是,只有 一个 允许的“来源”位于 OPTIONS 调用的响应标头中,而不是“*”。我通过从请求中读取来源并将其填充回响应中来实现这一点 - 可能绕过了限制的原始原因,但在我的用例中,安全性并不是最重要的。

我认为值得明确提及仅对一个来源的要求,因为 W3C 标准确实允许使用空格分隔的列表 - 但 Chrome 不允许! http://www.w3.org/TR/cors/#access-control-allow-origin-response-header 注意“实践”位。

【讨论】:

【参考方案4】:

把它放在你的初始化函数中:

$.ajaxSetup(
  xhrFields: 
    withCredentials: true
  
);

它会起作用的。

【讨论】:

你拯救了我的一天!在方法级别 withCredentials 对我不起作用。但是像这样在全球范围内它终于起作用了!谢谢。 小心它,因为它会将cookies发送到所有请求,其他域的ether(这是不期望的,并且通过require Access-Control-Allow-Credentials请求失败)【参考方案5】:

对于这个问题已经有很多很好的回答,但我认为这可能有助于澄清您希望发送会话 cookie 的情况,因为 cookie 域匹配,但它没有被发送,因为正在向不同的子域发出 AJAX 请求。在这种情况下,我有一个分配给 *.mydomain.com 域的 cookie,我希望将它包含在对 different.mydomain.com 的 AJAX 请求中strong>"。默认情况下,不会发送 cookie。您无需在会话 cookie 上禁用 HTTPONLY 即可解决此问题。您只需执行 wombling 建议的操作 (https://***.com/a/23660618/545223) 并执行以下操作。

1) 将以下内容添加到您的 ajax 请求中。

xhrFields:  withCredentials:true 

2) 将以下内容添加到不同子域中资源的响应标头中。

Access-Control-Allow-Origin : http://original.mydomain.com
Access-Control-Allow-Credentials : true

【讨论】:

【参考方案6】:

在尝试了其他解决方案但仍然无法正常工作后,我发现了我的问题所在。我将 contentType 从“application/json”更改为“text/plain”。

$.ajax(fullUrl, 
    type: "GET",
    contentType: "text/plain",
    xhrFields: 
         withCredentials: true
    ,
    crossDomain: true
);

【讨论】:

【参考方案7】:

我遇到了同样的问题,并且做了一些检查,我的脚本只是没有获取 sessionid cookie。

通过查看浏览器中的 sessionid cookie 值,我发现我的框架 (Django) 正在使用 HttpOnly 作为默认值传递 sessionid cookie。这意味着脚本无权访问 sessionid 值,因此不会将其与请求一起传递。当很多东西使用需要访问限制的 Ajax 时,HttpOnly 将成为默认值有点荒谬。

为了解决这个问题,我更改了一个设置 (SESSION_COOKIE_HTTPONLY=False),但在其他情况下,它可能是 cookie 路径上的“HttpOnly”标志

【讨论】:

不要这样做。它允许客户端脚本访问会话 cookie,这是最常见的 XSS 攻击媒介。 owasp.org/index.php/HttpOnly 即使我这样做了,浏览器也不会发送会话cookie lmao。【参考方案8】:

如果您是在localhost 或localhost 上的端口(例如localhost:8080)上进行开发,除了上面答案中描述的步骤之外,您还需要确保您没有在Set-中传递域值Cookie 标头。 您不能在 Set-Cookie 标头中将域设置为 localhost - 这是不正确的 - 只需省略域即可。

见Cookies on localhost with explicit domain和Why won't asp.net create cookies in localhost?

【讨论】:

【参考方案9】:

在本地主机和开发环境下设置 PHPSESSID cookie 问题只需 2 美分。我对本地主机上的 REST API 端点进行 AJAX 调用。假设它的地址是mysite.localhost/api/member/login/(我的开发环境中的虚拟主机)。

当我在 Postman 上执行此请求时,一切正常,并且响应设置了 PHPSESSID。

1234563 >

当我直接从同一域(即mysite.localhost/test/api/login.php)上的页面发出此请求时,PHPSESSID 设置得很好。

所以这是 @flu answer above 中提到的跨域源请求 cookie 问题

【讨论】:

【参考方案10】:

添加我的方案和解决方案,以防它帮助其他人。我在使用 RESTful API 时遇到了类似的情况。我的托管 html/Script/CSS 文件的 Web 服务器和公开 API 的应用程序服务器托管在同一个域上。 但是路径不同。

网络服务器 - mydomain/网页/abc.html

使用 abc.js 设置名为 mycookie

的 cookie

应用服务器 - mydomain/webapis/servicename.

调用了哪些 api

我期待 mydomain/webapis/servicename 中的 cookie 并尝试读取它,但它没有被发送。 从答案中阅读评论后,我检查了浏览器的开发工具 mycookie 的路径设置为“/webpages”,因此在对

的服务调用中不可用

mydomain/webapis/servicename

所以在从 jquery 设置 cookie 时,这就是我所做的 -

$.cookie("mycookie","mayvalue",**path:'/'**);

【讨论】:

【参考方案11】:

也许不是 100% 回答了这个问题,但我偶然发现了这个线程,希望在从 innovastudio 编辑器的资产管理器中通过 ajax 发布文件上传时解决会话问题。 最终解决方案很简单:他们有一个闪存上传器。禁用它(设置

var flashUpload = false;   

在asset.php中),灯又开始闪烁了。

由于这些问题很难调试,我发现在上传处理程序中添加以下内容将使您(好吧,在这种情况下是我)走上正确的轨道:

$sn=session_name();
error_log("session_name: $sn ");

if(isset($_GET[$sn])) error_log("session as GET param");
if(isset($_POST[$sn])) error_log("session as POST param");
if(isset($_COOKIE[$sn])) error_log("session as Cookie");
if(isset($PHPSESSID)) error_log("session as Global");

深入查看日志,我很快发现了丢失的会话,没有发送任何 cookie。

【讨论】:

我认为上面的例子行不通,因为当没有会话 cookie 时,$sn 的值是多少? (一个随机的,或者可能为 null),或者用户可以从 GET 值设置 session_name 例如session_name(isset($_GET['sess']) ? $_GET['sess'] : null);session_start(); 这样,他们会得到一个工作的东西 这正是我发现问题的方式:从这个 Flash 上传器发帖时没有会话。由于使用 GET 变量会话标识符是一个坏主意,并且 cookie 无法正常工作,因此我将其丢弃。谁在乎呢,反正闪存已经成为过去。

以上是关于为啥 jQuery 的 .ajax() 方法不发送我的会话 cookie?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 IE 10 拒绝通过 jQuery $.ajax 发送 POST 数据

为啥我的 AJAX 方法将表单输入发送到 URL?

我想知道为啥当我发送一个数组以使用 jquery ajax (django,jquery) 查看时发生错误

为啥这个对 C# 方法的 jquery ajax GET 调用不起作用?

为啥vue不使用ajax

对jquery中的$.ajax二次封装 从而多次调用 今天一整天都在想这个事情