我正在使用 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'
})
}
为什么?
最佳答案
我找到了解决方案。这个问题的核心是我的按钮触发 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响应 header ,但浏览器中没有存储任何内容。一件奇怪的事情是这个响应总是有 HttpOnly
不管我的 {httpOnly : true/false}
是在 cookie 字符串之后标记的服务器上的设置。在手动使用浏览器对页面做GET请求的情况下,HttpOnly
像往常一样受到尊重,并且设置了 cookie。
所以解决方案是设置credentials
作为include
允许跨源 cookie 发送。
async trySetCookie()
{
await fetch("http://localhost:5555/s",{
method: 'GET',
credentials: 'include'
})
}
此外,在服务器端,您需要使用新 header 手动允许特定来源:
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 都会被设置。仍然很高兴包含该 header 以消除错误。
如果您使用 cors
Express
的中间件它甚至更容易。您可以只使用这些选项
var corsOptions = {
origin: 'http://localhost:3000',
credentials: true
}
app.use(cors(corsOptions))
当然还有credentials: 'include'
客户端仍然需要。
关于javascript - fetch() 无法设置从服务器接收到的 cookie?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42710057/