为啥 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 中添加这些: 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 数据
我想知道为啥当我发送一个数组以使用 jquery ajax (django,jquery) 查看时发生错误