首页 > 解决方案 > 防止在 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

很感谢任何形式的帮助。不知道是什么原因造成的。

标签: node.jsexpresspassport.js

解决方案


实际上,您的问题与 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 响应标头,但需要在客户端内部添加更多代码。


推荐阅读