Why is jquery's .ajax() method not sending my session cookie?
在通过
我做错什么了?
我正在跨域方案中操作。在登录期间,远程服务器将set cookie header和
下一次对远程服务器的Ajax调用应该使用这个cookie。
CORS的
对于我来说,它看起来像jquery中的一个bug(或者至少在下一个版本中有这个特性)。
更新:
不会从Ajax响应中自动设置cookie(引文:http://aleembarwany.com/2006/11/14/atomy-of-a-well-designed-ajax-login-experience/)
为什么?
无法从响应获取cookie的值以手动设置它(http://www.w3.org/tr/xmlhttprequest/dom xmlhttprequest getresponseHeader)
我很困惑…
应该有一种方法要求
答:您应该使用http://api.jquery.com/jquery.ajax的
文档中的示例是:
1 2 3 4 5 6 | $.ajax({ url: a_cross_domain_url, xhrFields: { withCredentials: true } }); |
服务器正确回答这个请求也很重要。复制@fr_d_ric和@pebbl的评论:
所以当请求是:
1 2 | Origin: http://foo.example Cookie: pageAccess=2 |
服务器应响应:
1 2 3 4 | 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-u-credentials
Ajax调用仅在您调用的URL与调用脚本位于同一域时发送cookie。
这可能是一个跨域问题。
也许您在调用脚本位于
在这种情况下,您的选择是:
- 编写一个驻留在域B上的小代理,并将您的请求转发到域A。您的浏览器将允许您调用该代理,因为它与调用脚本位于同一服务器上。
然后,您可以将该代理配置为接受一个cookie名称和值参数,该参数可以发送到域A。但要使其工作,您需要知道cookie的名称和域A上服务器的值需要进行身份验证。 - 如果要获取JSON对象,请尝试使用JSONP请求。jquery支持这些。但是您需要在域A上修改您的服务,以便它返回有效的JSONP响应。
很高兴能帮上一点忙。
使用
1 | xhrFields: { withCredentials:true } |
作为jquery的一部分,Ajax调用只是解决方案的一部分。我还需要在我的资源的选项响应中返回头:
1 2 | Access-Control-Allow-Origin : http://www.wombling.com Access-Control-Allow-Credentials : true |
重要的是,只有一个允许的"来源"位于选项调用的响应头中,而不是"*"。我通过从请求中读取源代码并将其填充回响应中实现了这一点——可能绕过了限制的原始原因,但在我的用例中,安全性并不重要。
我认为有必要明确地提到只有一个源代码的要求,因为W3C标准允许使用一个空格分隔的列表——但Chrome不允许!http://www.w3.org/tr/cors/访问控制允许源站响应头注意"实践中"位。
把它放到init函数中:
1 2 3 4 5 | $.ajaxSetup({ xhrFields: { withCredentials: true } }); |
它会起作用的。
对于这个问题已经有很多很好的回答,但是我认为澄清在哪里发送会话cookie可能会有所帮助,因为cookie域匹配,但是由于Ajax请求被发送到不同的子域,所以不会发送会话cookie。在本例中,我有一个分配给*.mydomain.com域的cookie,我希望它包含在对不同.mydomain.com的Ajax请求中"。默认情况下,不会发送cookie。您不需要在会话cookie上禁用httponly来解决此问题。您只需要按照Wombling的建议(https://stackoverflow.com/a/23660618/545223)执行以下操作。
1)将以下内容添加到Ajax请求中。
1 | xhrFields: { withCredentials:true } |
2)将以下内容添加到不同子域中资源的响应头中。
1 2 | Access-Control-Allow-Origin : http://original.mydomain.com Access-Control-Allow-Credentials : true |
在尝试了其他的解决方案,但仍然没有使其发挥作用之后,我发现了我的案例中的问题所在。我将ContentType从"application/json"更改为"text/plain"。
1 2 3 4 5 6 7 8 | $.ajax(fullUrl, { type:"GET", contentType:"text/plain", xhrFields: { withCredentials: true }, crossDomain: true }); |
我也遇到了同样的问题,做了一些检查,我的脚本只是没有得到sessionid cookie。
通过查看浏览器中的sessionid cookie值,我发现我的框架(django)正在以httponly作为默认值传递sessionid cookie。这意味着脚本不能访问sessionid值,因此不能与请求一起传递它。有点可笑的是,当这么多东西使用需要访问限制的Ajax时,httpOnly将成为默认值。
为了解决这个问题,我更改了一个设置(session_cookie_httponly=false),但在其他情况下,它可能是cookie路径上的"httponly"标志。
在本地主机和开发环境下设置phpsessid cookie问题只需2美分。我对locahost上的RESTAPI端点进行Ajax调用。假设它的地址是
当我对邮递员执行这个请求时,一切都会好起来,phpsessid会随响应一起设置。
当我通过Ajax从浏览器同步代理页面(例如从浏览器地址行中的
122.133.1.110:3000/test/api/login.php 请求此端点时,请注意域与mysite.localhost 不同)phpsessid不会出现在cookie中。当我直接从同一个域(即
mysite.localhost/test/api/login.php 页)的页面发出这个请求时,phpsessid设置得很好。
所以这是一个跨来源的请求cookie问题,如上文@flu answer中所述。
如果您在
查看具有显式域的localhost上的cookies,为什么ASP.NET不在localhost中创建cookies?
也许不是100%回答这个问题,但是当Ajax从innovastudio编辑器的AssetManager发布一个文件上传时,为了解决会话问题,我偶然发现了这个线程。最终解决方案很简单:他们有一个闪存上载程序。禁用(设置
1 | var flashUpload = false; |
在asset.php)中,指示灯再次开始闪烁。
由于这些问题很难调试,我发现在上载处理程序中放入类似以下内容将使您(在本例中是我)进入正确的轨道:
1 2 3 4 5 6 7 | $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。