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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2870371/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 14:26:58  来源:igfitidea点击:

Why is jquery's .ajax() method not sending my session cookie?

jqueryajaxsessioncookies

提问by user345625

After logging in via $.ajax()to a site, I am trying to send a second $.ajax()request to that site - but when I check the headers sent using FireBug, there is no session cookie being included in the request.

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

What am I doing wrong?

我究竟做错了什么?

采纳答案by flu

AJAX calls only send Cookies if the url you're calling is on the same domain as your calling script.

如果您正在调用的 url 与您的调用脚本在同一个域中,则 AJAX 调用仅发送 Cookie。

This may be a Cross Domain Problem.

这可能是一个跨域问题。

Maybe you tried to call a url from www.domain-a.comwhile your calling script was on www.domain-b.com(In other words: You made a Cross Domain Call in which case the browser won't sent any cookies to protect your privacy).

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

In this case your options are:

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

  • Write a small proxy which resides on domain-b and forwards your requests to domain-a. Your browser will allow you to call the proxy because it's on the same server as the calling script.
    This proxy then can be configured by you to accept a cookie name and value parameter which it can send to domain-a. But for this to work you need to know the cookie's name and value your server on domain-a wants for authentication.
  • If you're fetching JSON objects try to use a JSONPrequest instead. jQuery supports these. But you need to alter your service on domain-a so that it returns valid JSONP responds.
  • 编写一个驻留在域 b 上的小代理,并将您的请求转发到域 a。您的浏览器将允许您调用代理,因为它与调用脚本在同一台服务器上。
    然后,您可以将此代理配置为接受可以发送到域 a 的 cookie 名称和值参数。但是要使其工作,您需要知道 cookie 的名称和值您在域上的服务器 - a 想要进行身份验证。
  • 如果您正在获取 JSON 对象,请尝试改用JSONP请求。jQuery 支持这些。但是您需要更改域 a 上的服务,以便它返回有效的 JSONP 响应。

Glad if that helped even a little bit.

很高兴如果这有一点帮助。

回答by Kangur

I am operating in cross-domain scenario. During login remote server is returning Set-Cookie header along with Access-Control-Allow-Credentialsset to true.

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

The next ajax call to remote server should use this cookie.

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

CORS's Access-Control-Allow-Credentialsis there to allow cross-domain logging. Check https://developer.mozilla.org/En/HTTP_access_controlfor examples.

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

For me it seems like a bug in JQuery (or at least feature-to-be in next version).

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

UPDATE:

更新:

  1. Cookies are not set automatically from AJAX response (citation: http://aleembawany.com/2006/11/14/anatomy-of-a-well-designed-ajax-login-experience/)

    Why?

  2. You cannot get value of the cookie from response to set it manually (http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-getresponseheader)

    I'm confused..

    There should exist a way to ask jquery.ajax()to set XMLHttpRequest.withCredentials = "true"parameter.

  1. AJAX 响应不会自动设置 Cookie(引用: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"参数。

ANSWER:You should use xhrFieldsparam of http://api.jquery.com/jQuery.ajax/

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

The example in the documentation is:

文档中的示例是:

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

It's important as well that server answers correctly to this request. Copying here great comments from @Frédéric and @Pebbl:

服务器正确响应此请求也很重要。在这里复制@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: *

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

So when the request is:

所以当请求是:

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

Server should respond with:

服务器应响应:

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

[payload]

Otherwise payload won't be returned to script. See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials

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

回答by wombling - Chris Paine

Using

使用

xhrFields: { withCredentials:true }

as part of my jQuery ajax call was only part of the solution. I also needed to have the headers returned in the OPTIONS response from my resource:

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

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

It was important that only oneallowed "origin" was in the response header of the OPTIONS call and not"*". I achieved this by reading the origin from the request and populating it back into the response - probably circumventing the original reason for the restriction, but in my use case the security is not paramount.

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

I thought it worth explicitly mentioning the requirement for only one origin, as the W3C standard does allow for a space separated list -but Chrome doesn't! http://www.w3.org/TR/cors/#access-control-allow-origin-response-headerNB the "in practice" bit.

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

回答by Alex Athlan

Put this in your init function:

把它放在你的 init 函数中:

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

It will work.

它会起作用。

回答by munchbit

There are already a lot of good responses to this question, but I thought it may be helpful to clarify the case where you would expect the session cookie to be sent because the cookie domain matches, but it is not getting sent because the AJAX request is being made to a different subdomain. In this case, I have a cookie that is assigned to the *.mydomain.comdomain, and I am wanting it to be included in an AJAX request to different.mydomain.com". By default, the cookie does not get sent. You do not need to disable HTTPONLY on the session cookie to resolve this issue. You only need to do what wombling suggested (https://stackoverflow.com/a/23660618/545223) and do the following.

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

1) Add the following to your ajax request.

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

xhrFields: { withCredentials:true }

2) Add the following to your response headers for resources in the different subdomain.

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

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

回答by Janno Teelem

After trying out the other solutions and still not getting it to work, I found out what the problem was in my case. I changed contentType from "application/json" to "text/plain".

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

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

回答by wiwa

I was having this same problem and doing some checks my script was just simply not getting the sessionid cookie.

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

I figured out by looking at the sessionid cookie value in the browser that my framework (Django) was passing the sessionid cookie with HttpOnly as default. This meant that scripts did not have access to the sessionid value and therefore were not passing it along with requests. Kind of ridiculous that HttpOnly would be the default value when so many things use Ajax which would require access restriction.

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

To fix this I changed a setting (SESSION_COOKIE_HTTPONLY=False) but in other cases it may be a "HttpOnly" flag on the cookie path

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

回答by jitin

If you are developing on localhostor a port on localhost such as localhost:8080, in addition to the steps described in the answers above, you also need to ensure that you are not passing a domain value in the Set-Cookie header.
You cannot set the domain to localhostin the Set-Cookie header - that's incorrect - just omit the domain.

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

See Cookies on localhost with explicit domainand Why won't asp.net create cookies in localhost?

请参阅具有显式域的 localhost 上的 Cookie以及为什么 asp.net 不在 localhost 中创建 cookie?

回答by Valentine Shi

Just my 2 cents on setting PHPSESSID cookie issue when on localhost and under dev environment. I make the AJAX call to my REST API endpoint on the locahost. Say its address is mysite.localhost/api/member/login/(virtal host on my dev environment).

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

  • When I do this request on Postman, things go fine and PHPSESSID is set with the response.

  • When I request this endpoint via AJAX from the Browsersync proxied page (e.g. from 122.133.1.110:3000/test/api/login.phpin my browser address line, see the domain is different vs mysite.localhost) PHPSESSID does not appear among cookies.

  • When I make this request directly from the page on the same domain (i.e. mysite.localhost/test/api/login.php) PHPSESSID is set just fine.

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

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

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

So this is a cross-origin origin request cookies issue as mentioned in @flu answer above

所以这是上面@flu回答中提到的跨源源请求 cookie 问题

回答by Codeek

Adding my scenario and solution in case it helps someone else. I encountered similar case when using RESTful APIs. My Web server hosting HTML/Script/CSS files and Application Server exposing APIs were hosted on same domain. However the path was different.

添加我的场景和解决方案,以防它对其他人有帮助。我在使用 RESTful API 时遇到过类似的情况。我托管 HTML/Script/CSS 文件的 Web 服务器和公开 API 的应用程序服务器托管在同一域中。然而路径不同。

web server - mydomain/webpages/abc.html

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

used abc.jswhich set cookie named mycookie

二手abc.js其设置cookie的命名的myCookie

app server - mydomain/webapis/servicename.

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

to which api calls were made

对其进行了 api 调用

I was expecting the cookie in mydomain/webapis/servicename and tried reading it but it was not being sent. After reading comment from the answer, I checked in browser's development tool that mycookie's path was set to "/webpages" and hence not available in service call to

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

mydomain/webapis/servicename

我的域名/ webapis/服务名称

So While setting cookie from jquery, this is what I did -

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

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