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

匿名 (未验证) 提交于 2019-12-03 01:29:01

问题:

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.

What am I doing wrong?

回答1:

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

This may be a Cross Domain Problem.

Maybe you tried to call a url from www.domain-a.com while 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).

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 JSONP request instead. jQuery supports these. But you need to alter your service on domain-a so that it returns valid JSONP responds.

Glad if that helped even a little bit.



回答2:

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

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

CORS's Access-Control-Allow-Credentials is there to allow cross-domain logging. Check https://developer.mozilla.org/En/HTTP_access_control for examples.

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

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.

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

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:

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



回答3:

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:

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

It was important that only one allowed "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.

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-header NB the "in practice" bit.



回答4:

Put this in your init function:

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

It will work.



回答5:

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.com domain, 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.

1) Add the following to your ajax request.

xhrFields: { withCredentials:true } 

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

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


回答6:

I was having this same problem and doing some checks my script was just simply not getting the 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.

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



回答7:

If you are developing on localhost or 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 localhost in the Set-Cookie header - that's incorrect - just omit the domain.

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



回答8:

You have to initialize the session before you trying to login.

For php, you have to do

session_start(); 

on the page from where you start the login ajax call.

So that the SESSIONID will be created and stored the browser cookie. And sent along with request header during the ajax call, if you do the ajax request to the same domain

For the successive ajax calls browser will use the SESSIONID that created and stored initially in browser cookie, unless we clear the browser cookie or do logout (or set another cookie)



回答9:

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

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


回答10:

Perhaps not 100% answering the question, but i stumbled onto this thread in the hope of solving a session problem when ajax-posting a fileupload from the assetmanager of the innovastudio editor. Eventually the solution was simple: they have a flash-uploader. Disabling that (setting

var flashUpload = false;    

in asset.php) and the lights started blinking again.

As these problems can be very hard to debug i found that putting something like the following in the upload handler will set you (well, me in this case) on the right track:

$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"); 

A dive into the log and I quickly spotted the missing session, where no cookie was sent.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!