为什么jquery的.ajax()方法没有发送我的会话cookie?

时间:2010-05-20 00:44:51

标签: jquery ajax session cookies

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

我做错了什么?

11 个答案:

答案 0 :(得分:359)

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

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

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

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

更新:

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

    为什么?

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

    我很困惑..

    应该有一种方法可以让jquery.ajax()设置XMLHttpRequest.withCredentials = "true"参数。

  3. <强>解答: 您应该使用xhrFields

    $.ajax({ url: a_cross_domain_url, xhrFields: { withCredentials: true } }); 参数

    文档中的示例是:

    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: *

    服务器正确回答此请求也很重要。在这里复制@Frédéric和@Pebbl的好评:

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

    所以当请求是:

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

    服务器应该回复:

    {{1}}

    否则有效负载不会返回脚本。请参阅:http://api.jquery.com/jQuery.ajax/

答案 1 :(得分:203)

如果您呼叫的网址与您的主叫脚本位于同一个域,则AJAX呼叫仅发送Cookie。

这可能是跨域问题。

当您的调用脚本在www.domain-a.com上时,也许您尝试从www.domain-b.com调用网址(换句话说:您进行了跨域调用,在这种情况下,浏览器不会向其发送任何Cookie保护您的隐私。)

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

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

如果这有点帮助的话,我很高兴。

答案 2 :(得分:46)

使用

xhrFields: { withCredentials:true }

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

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

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

我认为值得明确提到只有一个来源的要求,因为W3C标准确实允许空格分隔列表 - 但Chrome没有! http://www.w3.org/TR/cors/#access-control-allow-origin-response-header 注意事项&#34;在实践中&#34;位。

答案 3 :(得分:39)

将它放在你的init函数中:

$.ajaxSetup({
  xhrFields: {
    withCredentials: true
  }
});

它会起作用。

答案 4 :(得分:11)

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

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

xhrFields: { withCredentials:true }

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

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

答案 5 :(得分:5)

在尝试了其他解决方案后仍然没有让它工作,我发现问题出在我的案例中。我更改了#34; application / json&#34;中的contentType。 to&#34; text / plain&#34;。

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

答案 6 :(得分:3)

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

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

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

答案 7 :(得分:0)

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

请参阅Cookies on localhost with explicit domainWhy won't asp.net create cookies in localhost?

答案 8 :(得分:0)

在本地主机和开发环境下,仅花2美分就可以设置PHPSESSID cookie。我在locahost上对我的REST API端点进行AJAX调用。假设其地址为mysite.localhost/api/member/login/(我的开发环境中的虚拟主机)。

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

  • 当我从Browsersync代理页面通过AJAX请求此终结点时(例如,从我的浏览器地址行中的122.133.1.110:3000/test/api/login.php访问该域,请参见与mysite.localhost的域不同),PHPSESSID在cookie中不出现

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

这是@flu answer above

中提到的跨域起源请求cookie问题

答案 9 :(得分:0)

添加我的方案和解决方案,以防其他人使用。使用RESTful API时遇到类似情况。我托管HTML / Script / CSS文件的Web服务器和暴露API的Application Server托管在同一域中。 但是路径是不同的。

  

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

使用了 abc.js ,它设置了名为 mycookie

的cookie
  

应用服务器-mydomain / webapis /服务名称。

进行了api调用

我期望mydomain / webapis / servicename中的cookie并尝试读取它,但未发送。 阅读答案的评论后,我签入了浏览器的开发工具, mycookie的路径设置为“ / 网页”,因此在对

的服务调用中不可用
  

mydomain / webapis /服务名称

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

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

答案 10 :(得分:-5)

也许不是100%回答这个问题,但我偶然发现了这个线程,希望在ajax-从innovastudio编辑器的assetmanager发布文件上载时解决会话问题。 最终解决方案很简单:他们有一个flash-uploader。禁用(设置

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。