所以我正在实施 JWT 访问令牌/刷新令牌周期。我在 httpOnly cookie 中发送刷新令牌,并且想将其发送回服务器。
httpOnly cookie 出现在响应“Set-Cookie”标头中,但在 chrome 开发者工具的“应用程序”选项卡中不可见(我不确定这是否可以,有人说出于安全原因,httpOnly cookie 不会出现)。 这是我的代码:
CORS 选项:
const corsOptions = {
origin: "http://localhost:5173",
credentials: true, //access-control-allow-credentials:true
optionSuccessStatus: 200,
exposedHeaders: [
"x-auth-token",
"Access-Control-Allow-Origin",
"Access-Control-Allow-Credentials",
],
};
app.use(cookieParser());
app.use(cors(corsOptions));
这是我如何通过端点成功将cookie发送到客户端:
res
.cookie("refreshToken", refreshToken, {
httpOnly: true,
origin: "http://localhost:3000",
secure: true,
maxAge: 7 * 24 * 60 * 60 * 1000,
})
.header("x-auth-token", accessToken)
.send("User validated, token accesible from headers");
这是我用来收回令牌的中间件,但console.log打印未定义:
module.exports = function authorizeRefreshToken(req, res, next) {
try {
const refreshToken = req.cookie;
console.log("Refresh Token from client : ", refreshToken);
if (!refreshToken) return res.status(403).send("No token inside cookie.");
const decoded = jwt.verify(
refreshToken,
config.get("jwtPrivateKey"),
(err) => {
if (err) {
if (err.name === "TokenExpiredError") {
return res.status(403).send("Unauthorized");
} else {
console.log(err);
return res.status(400).send("An error with JWT occurred!");
}
}
}
);
req._id = decoded._id;
req.refreshToken = refreshToken;
next();
} catch (error) {
console.log("Error with the token", error);
}
};
这是前端的api调用:
const getAccessToken = async () => {
try {
const response = await axios.get(END_POINT, {
withCredentials: true,
});
const token = response.headers["x-auth-token"];
setAccessToken(token);
console.log("Access Token in useEffect : ", token);
} catch (error) {
console.error("AXIOS ERROR", error);
}
};
实际上,httpOnly cookie 确实出现在浏览器的“应用程序”选项卡中,但只是无法访问。如果您执行类似
document.cookie
的操作,则除了 httpOnly cookie 之外,“应用程序”选项卡中可用的所有 cookie 都将被输出。因此,httpOnly cookie 仅当您向服务器发出 http 请求时才可用。
但是,您在浏览器的“应用程序”选项卡中看不到
refreshToken
的原因可能是由于 Samesite
cookie 配置选项。使用 Samesite=Lax
或 Samesite=Strict
设置的 Cookie 不会与本地主机上的跨站点请求一起发送,特别是如果您的前端和后端托管在不同的端口上(在您的情况下分别为 http://localhost:5173
和 http://localhost:3000
)。但是,在部署中,这应该可行。
为了让您的
refreshToken
显示在本地主机开发中浏览器的“应用程序”选项卡中,您应该将 SameSite=None
添加到您的 cookie 配置属性中。
res
.cookie("refreshToken", refreshToken, {
httpOnly: true,
origin: "http://localhost:3000",
secure: true, //this works only on https protocol
maxAge: 7 * 24 * 60 * 60 * 1000,
sameSite: "None"
})
.header("x-auth-token", accessToken)
.send("User validated, token accesible from headers");
之所以需要在cookie配置中具有
sameSite:None
属性,是因为默认情况下,如果没有设置sameSite,则认为是Lax
。请参阅 MDN 链接