Node.Js+;express+;护照:Can';t注销用户

Node.Js+;express+;护照:Can';t注销用户,node.js,express,passport.js,Node.js,Express,Passport.js,我为一个Web服务器编写了一个JS脚本,其中包括使用passport和摘要策略的身份验证。我没有使用会话,但我尝试过使用会话,但它不会改变结果。浏览器请求“/登录”路由并显示内置登录对话框。身份验证工作正常,但我无法让用户“注销”。问题似乎是浏览器会记住登录凭据并自动重新发送。最终结果是,用户必须完全关闭浏览器才能注销,但这是此应用程序的一个问题。我知道一定有办法告诉浏览器不要这样做,但我还没弄明白 我想出了一个办法让浏览器再次显示登录对话框;强制验证函数返回false。然而,我还没有找到一种方

我为一个Web服务器编写了一个JS脚本,其中包括使用passport和摘要策略的身份验证。我没有使用会话,但我尝试过使用会话,但它不会改变结果。浏览器请求“/登录”路由并显示内置登录对话框。身份验证工作正常,但我无法让用户“注销”。问题似乎是浏览器会记住登录凭据并自动重新发送。最终结果是,用户必须完全关闭浏览器才能注销,但这是此应用程序的一个问题。我知道一定有办法告诉浏览器不要这样做,但我还没弄明白

我想出了一个办法让浏览器再次显示登录对话框;强制验证函数返回false。然而,我还没有找到一种方法来完成每一个会话。现在,如果一个人注销,所有人都将注销。这不是一个可行的解决办法

有人能告诉我我做错了什么吗?我想知道的一件事是,当浏览器发布到/logout路径时,我是否向浏览器返回了正确的响应(请参见结尾)。我返回res.json(“”),但也许我应该发送一个不同的响应,告诉浏览器忘记会话的凭据

我的代码如下。非常感谢您的任何见解。先谢谢你

T

res.redirect('/')
将结束响应,您不能随后调用write()、end()、send()、json()等

就这样,

app.post('/logout', function(req, res){
  req.logOut();
  res.redirect("/");
});
反序列化用户应返回用户而不是id:

passport.deserializeUser(function(id, done) {
    findUser(id, function(err, user) {
       if(err) {
          done(err)
       } else {
          done(null, user);
       }
    }
});

我做了一个简短的讨论,我意识到摘要用户名/密码存储在浏览器上(不在服务器上),所以req.logout没有帮助,无法从服务器上清除它。您只需关闭浏览器并再次打开,即意味着注销

您可以在cookie或会话中使用变量将会话标记为注销,但我认为我们不应该这样做,因为用户名/密码仍在浏览器中


这是消化

您可以尝试以下方法

req.session.destroy()
req.logout()
res.redirect('/')

如果您正在使用某种形式的会话存储用于持久会话(例如Redis),则保存会话的新状态非常重要。我用类似的设置尝试了上面的代码,它似乎对我有效

服务器需要以某种方式通知web浏览器他需要刷新登录信息(MD5摘要)。 为此,您可以发送401错误代码,通常浏览器将显示登录弹出消息

顺便说一句,所有这些会话技巧都是无用的,因为浏览器已经具备了自动登录所需的所有信息

因此,您可以尝试下一个代码:

req.logout();
res.send("logged out", 401);

派对有点晚了,但我在搜索答案时在谷歌上找到了这条线索,对我来说没有任何效果。最后,我终于解决了这个问题,所以我想我可以在这里为将来可能阅读此文章的任何人发布解决方案


因此,基本上,我使用node.js、express、passport(local)和referencedb作为存储,我在
req.logout()方面遇到了问题不让我注销

我的设置:

var express = require( 'express' );
var passport = require( 'passport' );
var session = require( 'express-session' );
var RDBStore = require( 'express-session-rethinkdb' )( session );
我尝试了很多东西,但都不起作用,所以最后我决定手动完成,方法是自己从数据库中删除会话记录

以下是我使用的代码: app.get('/logout',函数(req,res,next){


因此,我希望这对某人有所帮助:)

使用全局变量
forceLogin
是一个非常糟糕的主意,因为它将在所有用户的所有请求中共享。同意,正如我在原始帖子中提到的。这就是为什么我希望有一个更好的解决方案。它不应该是
app.get('/logout')吗
我不明白为什么app.post或app.get会有不同。无论如何,我尝试过,结果都是一样的。
app
也是一个全局变量。因此,使用
app.set
/
app.get
与使用全局变量是一样的。
res.session
是存储会话特定数据的正确位置。我做了这些e更正,但浏览器仍然没有“注销”。好的,你给了我一个主意。这似乎告诉浏览器我已经注销:app.post('/logout',function(req,res){req.logout();console.log(“logout”);res.send(401,“unauthorized”);不,这意味着我的解决方案不起作用。另请参阅req.session.destroy()使会话对象未定义。正在尝试使用passport http注销,而此oneliner拯救了我的一天。谢谢!回答太好了!问您如何设置passport local以连接RejectionDB会不会很无礼?我在存储值和密码哈希等的创建过程中遇到了难题。非常感谢!我只是来这里发布这篇文章答案完全正确。我也手动完成了这项工作,并使用RejectionDB作为我的会话存储,并且具有完全相同的逻辑。
var express = require( 'express' );
var passport = require( 'passport' );
var session = require( 'express-session' );
var RDBStore = require( 'express-session-rethinkdb' )( session );
    if ( req.isUnauthenticated() ) {

        // you are not even logged in, wtf
        res.redirect( '/' );

        return;

    }

    var sessionCookie = req.cookies['connect.sid'];

    if ( ! sessionCookie ) {

        // nothing to do here
        res.redirect( '/' );

        return;

    }

    var sessionId = sessionCookie.split( '.' )[0].replace( 's:', '' );

    thinky.r.db( 'test' ).table( 'session' ).get( sessionId ).delete().run().then( function( result ) {

        if ( ! result.deleted ) {

            // we did not manage to find session for this user
            res.redirect( '/' );

            return;

        }

        req.logout();
        res.redirect( '/' );

        return;

    });

});