Node.Js + express + Passport:无法注销用户

时间:2013-12-12 15:44:27

标签: node.js express passport.js

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

我想出了一个让浏览器再次显示登录对话框的黑客行为;强制认证功能返回false。但是,我还没有找到一种方法来执行每个会话。现在,如果一个人退出,每个人都会退出。这不是一个可行的解决方案。

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

我的代码如下。非常感谢任何见解。提前谢谢。

Ť

var passport = require('passport'), 
    DigestStrategy = require('passport-http').DigestStrategy;

var express = require('express');
var app = express();
app.configure(function () {
    app.use(
        "/", //the URL throught which you want to access to you static content
        express.static('./www') //where your static content is located in your filesystem
    );
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.session({ secret: 'keep moving forward' }));
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);


});
app.listen(80); //the port you want to use


/**
 * CORS support.
 */

app.all('*', function(req, res, next){
  if (!req.get('Origin')) return next();
  // use "*" here to accept any origin
  // For specific domain, do similar: http://localhost'
  // Use an array for multiple domains, like [http://localhost', 'http://example.com' ]
  res.set('Access-Control-Allow-Origin', '*' );
  res.set('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  res.set('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Authorization');
  next();
});


//
// Configure passport authentication
//


// Used to force the browser to display the login screen again.
var forceLogin = false;
passport.use(new DigestStrategy({ qop: 'auth' },
  function(username, done ) { 

  if ( !forceLogin )
  {
    return done(null, username, "nimda");
  }
  else
  {
    //
    // Forces the browser to request the user name again by returning a failure to its last request.
    //
    console.log ( "forcing user to log in"  );
    forceLogin = false;
    return done(null, false);
  }
));

passport.serializeUser(function(user, done) {

    console.log( "serialize user " + user.toString() );
    done(null, user.toString());
});

passport.deserializeUser(function(id, done) {
    console.log( "deserialize user " + id.toString() );
    done(null, id);
});

app.post('/login', passport.authenticate('digest', { session: true }),
  function(req, res) {
    console.log( "/login");
    res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
    res.json({ id: req.user.id, username: req.user.username });
 }); 

app.post('/logout', function(req, res){

  req.logOut();

  // NOTE: Same results as req.logout
  //
  //  req.session.destroy(function (err) {
  //   res.redirect('/'); 
  //  });

  res.redirect("/");

  // flag to force a login
  forceLogin = true;

  console.log( "logout");

  // Is this the proper return to the browser?
  return res.json("");
});

4 个答案:

答案 0 :(得分:6)

您可以尝试以下

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

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

答案 1 :(得分:4)

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

顺便说一下,所有这些带会话的技巧都没用,因为浏览器已经拥有了自动登录所需的全部信息。

所以你可以尝试下一个代码:

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

答案 2 :(得分:4)

派对有点晚了,但我在搜索答案时在Google上发现了这个帖子,对我来说没什么用。最后,我能够解决它,所以我认为我可以在这里为任何可能在将来阅读此内容的人发布解决方案。

所以基本上,我使用node.js,express,passport(local)和rethinkdb作为我的存储空间,我遇到了NavigationCompleted没有让我退出的问题。

我的设置:

def process(value):
    # do something with the value

for key,value_list in dict_of_lists:
    for value in value_list:
        process(value)

我尝试了很多东西而且没有任何工作,所以最后我决定手动执行此操作,方法是自己从数据库中删除会话记录。

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

req.logout();

所以我希望这有助于某人:)

答案 3 :(得分:0)

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

就像这样:

app.post('/logout', function(req, res){
  req.logOut();
  res.redirect("/");
});

deserializeUser应返回用户而不是id:

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

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

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

这是摘要!