我找到了解决方案。这个问题的核心是我的按钮触发fetch
是在http://localhost:3000/
。该服务器是http://localhost:5555/
(我是我自己的机器上模拟真实环境)
的问题是,这fetch
通话
async trySetCookie()
{
await fetch("http://localhost:5555/s",{
method: 'GET',
credentials: 'same-origin'
})
}
没有credentials
,浏览器无法发送或通过fetch
(https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials)
接收cookies
与credentials
as same-origin
我可以看到来自服务器的响应头Set-Cookie
中的cookie,但没有任何内容存储在浏览器中。奇怪的是,无论服务器上的我的{httpOnly : true/false}
设置如何,此响应始终都会在Cookie字符串后标记HttpOnly
。在手动使用浏览器到页面执行GET请求的情况下,HttpOnly
像往常一样受到尊重,并设置了Cookie。
因此,解决方案是将credentials
设置为include
以允许跨源cookie发送。
async trySetCookie()
{
await fetch("http://localhost:5555/s",{
method: 'GET',
credentials: 'include'
})
}
此外,在服务器端,你需要手动允许特定的原产地与新标题:
app.get("/s", (req,res) => {
res.cookie("bsaSession", req.session.id, {httpOnly:false})
res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
res.header('Access-Control-Allow-Credentials','true'
res.send("set")
})
不这样做会导致
XMLHttpRequest cannot load http://localhost:5555/s. Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true.
但cookie将不管这个错误如何设置。仍然很高兴能够包含该标题来消除错误。
如果您使用cors
中间件for Express
它更容易。你可以使用这些选项
var corsOptions = {
origin: 'http://localhost:3000',
credentials: true
}
app.use(cors(corsOptions))
当然credentials: 'include'
的,仍然是需要在客户端。
“它不设置cookie”---你怎么知道的?浏览器是否发送了请求头中的cookie? – zerkms
我查看了Safari调试控制台>存储> Cookies。当我点击调用'trySetCookie()'的按钮时,列表不会改变。但是,当我直接进入该页面时,该列表立即添加了新的Cookie。 – 5argon
那么,你在响应头文件中看到了“Set-Cookie”吗?该脚本是否在同一个端口上运行? – zerkms