我正在使用Express.js服务器。使用cookie-parser
我打开了此端点
app.get("/s", (req,res) => {
res.cookie("bsaSession", req.session.id)
res.send("set cookie ok")
})
当我手动使用浏览器http://localhost:5555/s
我运行的网站时,浏览器调试控制台显示已经应用了cookie。
但是,当我使用fetch
API来执行等效操作时,它不会设置cookie。
async trySetCookie()
{
await fetch("http://localhost:5555/s",{
method: 'GET',
credentials: 'same-origin'
})
}
为什么?
答案 0 :(得分:3)
我找到了解决方案。这个问题的核心是我触发fetch
的按钮位于http://localhost:3000/
。服务器在http://localhost:5555/
上(我在自己的机器上模拟真实环境)
问题在于此fetch
调用
async trySetCookie()
{
await fetch("http://localhost:5555/s",{
method: 'GET',
credentials: 'same-origin'
})
}
如果没有credentials
,则浏览器无法通过fetch
发送或接收Cookie(https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials)
credentials
为same-origin
我可以在Set-Cookie
响应标头中看到来自服务器的Cookie,但浏览器中没有存储任何内容。一个奇怪的事情是,无论我在服务器上的HttpOnly
设置如何,这个响应总是在cookie字符串之后标记{httpOnly : true/false}
。如果手动使用浏览器到页面执行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
Express
中间件,那就更容易了。您可以使用这些选项
var corsOptions = {
origin: 'http://localhost:3000',
credentials: true
}
app.use(cors(corsOptions))
当然,客户端仍然需要credentials: 'include'
。
答案 1 :(得分:1)
否则5argon的解决方案对我来说很棒,但是我不得不将origin
的显式变量设置为true
。所以在后端:
app.use(
cors({
origin: true,
credentials: true,
})
);
并且正在获取:
fetch("http://localhost:5555/s", {
method: 'GET',
credentials: 'include'
})