我正在使用$ .ajax发出ajax请求。响应设置了Set-Cookie
标题(我已在Chrome开发工具中对此进行了验证)。但是,浏览器在收到响应后不设置cookie!当我导航到我的域中的另一个页面时,不会发送cookie。 (注意:我没有做任何跨域的ajax请求;请求与文档在同一个域中。)
我错过了什么?
编辑:以下是我的ajax请求的代码:
$.post('/user/login', JSON.stringify(data));
此处是请求,如Chrome开发工具所示:
Request URL:https://192.168.1.154:3000/user/login
Request Method:POST
Status Code:200 OK
Request Headers:
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:35
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
DNT:1
Host:192.168.1.154:3000
Origin:https://192.168.1.154:3000
Referer:https://192.168.1.154:3000/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36
X-Requested-With:XMLHttpRequest
Form Data:
{"UserId":"blah","Password":"blah"}:
响应:
Response Headers:
Content-Length:15
Content-Type:application/json; charset=UTF-8
Date:Sun, 16 Mar 2014 03:25:24 GMT
Set-Cookie:SessionId=MTM5NDk0MDMyNHxEdi1CQkFFQ180SUFBUkFCRUFBQVRfLUNBQUVHYzNSeWFXNW5EQXNBQ1ZObGMzTnBiMjVKWkFaemRISnBibWNNTGdBc1ZFcDNlU3RKVFdKSGIzQlNXRkkwVjJGNFJ6TlRVSHA0U0ZJd01XRktjMDF1Y1c1b2FGWXJORzV4V1QwPXwWf1tz-2Fy_Y4I6fypCzkMJyYxhgM3LjVHGAlKyrilRg==; HttpOnly
答案 0 :(得分:51)
Path
选项很重要。如果您设置Path=/
,例如:
Set-Cookie:SessionId=foo; Path=/; HttpOnly
...然后当您导航到其他页面时,浏览器将设置cookie。如果不设置Path
,浏览器将使用“默认”路径。显然,AJAX请求设置的cookie的默认路径与直接导航到页面时使用的默认路径不同。我正在使用Go / Martini,所以在服务器端我这样做:
session.Options(session.Options{HttpOnly: true, Path:"/"})
我猜想Python / Ruby /等等。有类似的机制来设置Path
。
答案 1 :(得分:34)
如果您使用新的fetch
API,可以尝试添加credentials
:
fetch('/users', {
credentials: 'same-origin'
})
这就是为我解决的问题。
特别是,使用polyfill:https://github.com/github/fetch#sending-cookies
答案 2 :(得分:14)
@ atomkirk的answer并不适用于我,因为
fetch
API 但答案帮助我实现了这些飞跃:
fetch
API CORS请求needs {credentials:'include'}
发送&接收cookie
对于CORS请求,请使用“include”值以允许发送 其他域的凭据:
fetch('https://example.com:1234/users', { credentials: 'include' })
...要从服务器选择接受 Cookie,您必须使用凭据选项。
{credentials:'include'}
只需设置xhr.withCredentials=true
if (request.credentials === 'include') { xhr.withCredentials = true }
所以plain Javascript/XHR.withCredentials是重要的部分。
如果您使用的是jQuery,则can set withCredentials使用$.ajaxSetup(...)
$.ajaxSetup({ crossDomain: true, xhrFields: { withCredentials: true } });
如果您使用的是Angular,$http
service config arg会接受withCredentials
属性:
$http({ withCredentials: true });
至于请求,xhr.withCredentials=true
; Cookie标头已发送
在我更改xhr.withCredentials=true
Cookie
请求标头。更改后xhr.withCredentials=true
Cookie
请求标头,因此我的服务器将我视为“已验证”至于响应:服务器可能需要某些Access-Control- *标题
例如,我将服务器配置为返回这些标头:
在我将此服务器端更改为响应标头之前,Chrome在控制台中记录了错误,如
无法加载
https://{saml-domain}/saml-authn
:来自https://{saml-domain}/saml-redirect
的重定向已被CORS政策阻止:响应中
'Access-Control-Allow-Credentials'
标头的值为''
,当请求的凭据模式为'true'
时,该值必须为'include'
。因此,不允许原点https://{your-domain}
访问。XMLHttpRequest发起的请求的凭据模式由withCredentials属性控制。
更改此Access- *标头后,Chrome未记录错误;浏览器让我检查所有后续请求的经过身份验证的响应。
答案 3 :(得分:1)
这可以帮助某人随机遇到这个问题。
我发现即使服务器没有证书,并且使用https://而不是http://来强制使用URL,Chrome仍抱怨会解决此问题。
答案 4 :(得分:0)
就我而言,Cookie大小超过4096字节(谷歌浏览器)。我有一个动态Cookie有效负载,该负载会增加大小。
如果Cookie超出浏览器限制,浏览器将忽略set-cookie
响应标头,并且不会设置Cookie。
See here了解每个浏览器的Cookie大小限制。
我知道这不是解决方案,但这是我的问题,我希望它可以帮助某人:)