问题描述
我一直试图解决这个问题几天。在CORS请求上设置cookie。我看到过相互矛盾的文章和答案,有人说只要XHR请求将 withCredentials
设置为true,并且服务器发送相应的标题,浏览器就应该尊重 Set-Cookie
标头。但是,在我的测试中,情况并非如此。
I've been trying to tackle this problem for a few days. Setting cookies on CORS requests. I've seen conflicting articles and answers, some saying that as long as the XHR request has withCredentials
set to true, and the server sends the appropriate headers, the browser should respect the Set-Cookie
header. However, in my testing this has not been the case.
const http = require('http');
const fs = require('fs');
// Pretty colors
const colors = {
purple: '\033[95m',
orange: '\033[93m',
blue: '\033[97m',
underline: '\033[4m',
bold: '\033[1m',
reset: '\033[0m'
}
const server = http.createServer(function (req, res) {
//Console logs to verify what's getting hit.
console.log(colors.purple + colors.underline + 'Hit it!' + colors.reset);
console.log(colors.orange + colors.bold + 'url:' + colors.reset, req.url);
if (/\/cookie/.test(req.url)) {
console.log(colors.blue + 'We need to cook(ie) Jesse\n' + colors.reset);
// Generate a random string in a rather convoluted way.
var randomStr = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(36) +
Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(36) +
Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(36);
randomStr = new Buffer(randomStr.toString(), 'binary').toString('base64');
// All .dev domains pointed to localhost via dnsmasq, though a hosts file
// Update should also do the trick.
res.writeHead(200, {
'Set-Cookie': 'ajaxTestCookie=cookie' + randomStr + '; Domain=.example.dev; HttpOnly',
'Access-Control-Allow-Origin': 'http://example.dev:3999',
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Allow-Methods': 'GET, POST',
'Access-Control-Allow-Headers': 'Content-Type, Set-Cookie, *'
});
return res.end('OK!');
}
console.log(colors.blue + 'We\'re having fun at the HTML!\n' + colors.reset);
// Send out html file.
fs.readFile('./cookies.html', function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Failure to launch!');
}
res.end(data.toString());
});
});
server.listen(3999);
cookies.html
cookies.html
<html>
<head>
<title>Cookie Test</title>
</head>
<body>
<button class="getCookie">Get Cookies!</button>
<script>
(function() {
document.querySelector(".getCookie").addEventListener("click", function(e) {
console.log("test");
var req = new XMLHttpRequest();
req.open("GET", "http://localhost:3999/cookie", true);
req.onload = function() {
console.log(req.responseText);
};
req.withCredentials = true;
req.send();
});
}());
</script>
</body>
</html>
我已经尝试在Firefox Developer Edition和Chrome上测试这个,并且cookie不会设置除非页面直接访问。
I've tried testing this on both Firefox Developer Edition and Chrome, and the cookies will not set unless the page is accessed directly.
我有什么遗漏让cookie处理CORS请求吗?
Is there anything I'm missing to get cookies working on CORS requests?
推荐答案
不明显的是,服务器设置的cookie,至少在CORS请求中,并且可能(可能)在所有请求中限制在与服务器相同的域中。
What wasn't immediately obvious is that cookies set by the server, at least in CORS requests, and possibly (probably) in all requests are limited to the same domain as the server.
const http = require('http');
const fs = require('fs');
// Pretty colors
const colors = {
purple: '\033[95m',
orange: '\033[93m',
blue: '\033[97m',
underline: '\033[4m',
bold: '\033[1m',
reset: '\033[0m'
}
const server = http.createServer(function (req, res) {
//Console logs to verify what's getting hit.
console.log(colors.purple + colors.underline + 'Hit it!' + colors.reset);
console.log(colors.orange + colors.bold + 'url:' + colors.reset, req.url);
if (/\/cookie/.test(req.url)) {
console.log(colors.blue + 'We need to cook(ie) Jesse\n' + colors.reset);
// Generate a random string in a rather convoluted way.
var randomStr = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(36) +
Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(36) +
Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(36);
randomStr = new Buffer(randomStr.toString(), 'binary').toString('base64');
// All .dev domains pointed to localhost via dnsmasq, though a hosts file
// Update should also do the trick.
res.writeHead(200, {
'Set-Cookie': 'ajaxTestCookie=cookie' + randomStr + '; domain=.example.dev; HttpOnly',
'Access-Control-Allow-Origin': 'http://example.dev:3999',
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Allow-Methods': 'GET, POST',
'Access-Control-Allow-Headers': 'Content-Type, Set-Cookie, *'
});
return res.end('OK!');
}
console.log(colors.blue + 'We\'re having fun at the HTML!\n' + colors.reset);
// Send out html file.
fs.readFile('./cookies.html', function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Failure to launch!');
}
res.end(data.toString());
});
});
server.listen(3999); // api.example.dev:3999, for example
cookies.html
cookies.html
<html>
<head>
<title>Cookie Test</title>
</head>
<body>
<button class="getCookie">Get Cookies!</button>
<script>
(function() {
document.querySelector(".getCookie").addEventListener("click", function(e) {
console.log("test");
var req = new XMLHttpRequest();
// Request succeeds, but cookie will not be set!
// req.open("GET", "http://localhost:3999/cookie", true);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// This line, however, will work, assuming this page is on
// the same domain, or a subdomain of the same domain.
// (For example test.example.dev and api.example.dev)
// As long as the Access-Control-Allow-Origin Header is
// properly set to allow the domain.
req.open("GET", "http://api.example.dev:3999/cookie", true);
req.onload = function() {
console.log(req.responseText);
};
req.withCredentials = true;
req.send();
});
}());
</script>
</body>
这篇关于使用CORS请求设置Cookie的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!