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

在通过$.ajax()登录到一个网站后,我试图向该网站发送第二个$.ajax()请求-但当我检查使用FireBug发送的报头时,请求中没有会话cookie。

我做错了什么?

387544 次浏览

AJAX调用仅在您调用的url与调用脚本在同一域中时发送cookie。

这可能是一个跨域问题。

也许你试图从www.domain-a.com调用一个url,而你的调用脚本在www.domain-b.com上(换句话说:你做了一个跨域调用,在这种情况下浏览器不会发送任何cookie来保护你的隐私)。

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

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

如果这能帮到你就好了。

我在跨域场景下操作。在登录期间,远程服务器返回set - cookie头,并将Access-Control-Allow-Credentials设置为true。

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

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

对我来说,这似乎是JQuery的一个bug(或者至少是下一个版本的新特性)。

更新:

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

    为什么?< / p >

  2. 你不能从响应中获取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的精彩评论:

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

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

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

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

使用

xhrFields: { withCredentials:true }

作为我的jQuery ajax调用的一部分只是解决方案的一部分。我还需要有从我的资源的选项响应返回的头:

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

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

我认为值得明确提到的要求只有一个起源,因为W3C标准允许空格分隔列表-但Chrome不! http://www.w3.org/TR/cors/#access-control-allow-origin-response-header

.

.

.

对于这个问题已经有很多很好的回答,但我认为澄清一下这种情况可能会有所帮助,即您希望由于cookie域匹配而发送会话cookie,但由于AJAX请求是发送到另一个子域而没有发送会话cookie。在这种情况下,我有一个分配给* .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
也许不是100%回答这个问题,但我无意中发现了这个线程,希望解决一个会话问题,当ajax从innovastudio编辑器的资产管理器上传文件时。 最终解决方案很简单:他们有一个flash上传器。禁用that (setting

.
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。

把这个放在你的init函数中:

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

它会起作用的。

如果你在localhost或本地主机上的端口(如localhost:8080)上开发,除了上面回答中描述的步骤外,你还需要确保你没有在Set-Cookie报头中传递域值 你不能在set - cookie头中将域设置为localhost——这是不正确的——只需省略域即可。< / p >

参见具有显式域的本地主机上的cookie为什么asp.net不在localhost中创建cookie ?

在尝试了其他解决方案后,仍然没有奏效,我发现了我的问题所在。我把contentType从“application/json”改为“text/plain”。

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

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

  • 当我在邮差上做这个请求时,事情进展顺利,PHPSESSID被设置为响应。

  • 当我通过AJAX从Browsersync代理页面请求这个端点时(例如,从我的浏览器地址行122.133.1.110:3000/test/api/login.php,看到域是不同的vs mysite.localhost) PHPSESSID不会出现在cookie中。

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

所以这是一个跨源源请求cookie问题,如@flu 以上回答所述

添加我的场景和解决方案,万一它能帮助别人。我在使用RESTful api时遇到过类似的情况。我的承载HTML/Script/CSS文件的Web服务器和公开api的Application server托管在同一个域中。

mydomain/网页/abc.html

使用abc.js设置cookie名为mycookie

应用服务器- mydomain/webapi/servicename. txt

对哪个API调用

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

的服务调用中不可用

mydomain / webapi /名

所以当设置cookie从jquery,这是我所做的-

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

当您尝试发送跨站点请求时发生此错误。 我怎么解决这个问题?< / p >

在nginx配置文件中添加

add_header Access-Control-Allow-Origin '*.domain.com'
add_header Access-Control-Allow-Credentials 'true';

在“domain.com”中,我试图发送ajax请求

$.ajax({
url: sub.domain.com,
xhrFields: {
withCredentials: true
}
});