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

use*_*576 7 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("");
});
Run Code Online (Sandbox Code Playgroud)

小智 6

您可以尝试以下方法

req.session.destroy()
req.logout()
res.redirect('/')
Run Code Online (Sandbox Code Playgroud)

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

  • req.session.destroy()使会话对象不确定. (3认同)

小智 5

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

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

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

req.logout();
res.send("logged out", 401);
Run Code Online (Sandbox Code Playgroud)

  • 试图使用passport-http注销,这个oneliner拯救了我的一天。谢谢! (2认同)

dam*_*hat 0

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

像这样:

app.post('/logout', function(req, res){
  req.logOut();
  res.redirect("/");
});
Run Code Online (Sandbox Code Playgroud)

deserializeUser 应该返回一个用户而不是 id:

passport.deserializeUser(function(id, done) {
    findUser(id, function(err, user) {
       if(err) {
          done(err)
       } else {
          done(null, user);
       }
    }
});
Run Code Online (Sandbox Code Playgroud)

我进行了简短的讨论,我意识到摘要用户名/密码存储在浏览器上(而不是服务器上),因此 req.logout 没有帮助,没有办法从服务器中清除它。您只需关闭浏览器并再次打开就意味着注销。

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

是消化了!