node.js - 防止在 Chrome 上注销的 Cookie(PassportJS 和 Express)
问题描述
我今天刚刚在我的网站上设置了用户功能,但 Chrome 上似乎存在 cookie 问题,阻止我在以用户身份登录时退出。
当我单击注销按钮时,我被带回主页,但我仍然登录。我在 /logout 路由中放置了一些 console.logs,当我访问路由时它们似乎没有触发.
如果我刷新浏览器 cookie,我可以注销一次。如果我再次登录,我将无法再注销。很奇怪。如果我使用任何其他浏览器(或我的手机),我可以毫无问题地始终注销。如果我在 Chrome 的隐身标签中,它也可以工作。
我已经尝试了所有可以删除 cookie 的代码(req.session.destroy() 等),但都无济于事。
这是我的代码:
// 设置
app.use(require("express-session")({
secret: "Something",
resave: false,
saveUninitialized: false
}));
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(function(req, res, next) {
res.locals.currentUser = req.user;
res.locals.error = req.flash("error");
res.locals.success = req.flash("success");
next();
});
// 所有路由
app.get("/signup", function(req, res) {
res.render("signup.ejs");
});
app.post("/signup", function(req, res) {
User.register(new User({username: req.body.username}), req.body.password, function(err, newUser) {
if (err) {
console.log(err);
} else {
passport.authenticate("local")(req, res, function() {
req.flash("success", "You're now registered in as " + newUser.username + "!");
res.redirect(301, "/");
});
}
})
});
app.get("/login", function(req, res) {
res.render("login.ejs");
});
app.post("/login", passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login"
}), function(req, res) {
});
app.get("/logout", function(req, res) {
req.logout();
req.flash("success", "You have logged out!");
res.redirect(301, "/");
});
//HTML(使用 EJS)
<div class="nav__user">
<% if (!currentUser) { %>
<a href="/login" class="loginButton">Login</a>
<a href="/signup" class="signupButton">Sign Up</a>
<% } else { %>
<p><%= currentUser.username %></p>
<a href="/logout">Log Out</a>
<% } %>
</div>
而且,如果有任何帮助,这就是我在 Chrome 网络选项卡中看到的内容:
Response Headers:
HTTP/1.1 301 Moved Permanently
x-powered-by: Express
location: /
vary: Accept
content-type: text/html; charset=utf-8
content-length: 58
date: Sat, 05 Jan 2019 22:27:19 GMT
X-BACKEND: apps-proxy
Request Headers:
Provisional headers are shown
Referer: https://webdevbootcamp-osaisus.c9users.io/
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/71.0.3578.98 Safari/537.36
很感谢任何形式的帮助。不知道是什么原因造成的。
解决方案
实际上,您的问题与 cookie 无关。
Chrome 将缓存HTTP 301
接收到的 HTTP GET 请求的响应代码(这很有意义,因为 301 被定义为“永久移动”)。此永久重定向数据存储在与保存图像或脚本等资产的缓存不同的位置,并且不会被仅适用于这些资产的“空缓存和硬重新加载”等命令丢弃。
如果您让 Chrome 进入这种状态,有几种方法可以清除这些数据。有关详细信息,请参阅此超级用户问题,尤其是提到的答案chrome://net-internals
或 Chrome 开发人员控制台。
还有几种方法可以避免触发此行为。一种是将 Cache-Control 标头添加到您的响应中,/logout
如下所述:
您可以将缓存控制标头添加到 301,我们将遵循它们(到期等)
正确的做法是使用响应代码进行重定向,而不是HTTP 301
表示“您要求的东西永远消失了,现在就住在这里”。这里的意见似乎有所不同,但 302 或 307 可能是正确的选择。
另一种选择是将您的 Express 路由.post
从当前更改为 a.get
并编写一些 Javascript 以/logout
在单击按钮时让您的浏览器 POST 到。这不需要在服务器上设置额外的 HTTP 响应标头,但需要在客户端内部添加更多代码。
推荐阅读
- javascript - 我怎样才能让这个下拉列表显示所有五十个州而不是“选项#”
- docker - 如何从 docker 容器访问 docker cmd?
- c++ - 您如何将 std::unique_ptr 初始化为引用
- ubuntu - WSL:Cabal 无法解决依赖关系。容器,二进制
- python - API 调用在工作数百次后失败……有什么想法吗?
- spring-boot - 如何修复:java.lang.NoClassDefFoundError: org/springframework/core/env/EnvironmentCapable?
- php - 如何基于查询选择雄辩在laravel中使用用户授权
- python - Python 的 SpaCy EntityRuler 没有返回任何结果
- python - 为什么 split() 不分隔列表输出中字符串中的每个字符?
- html - 我可以让 flexbox 元素 flex-wrap 2 x 2 而不是 1 x 1 吗?