node.js 如何使用护照将“记住我”添加到我的应用程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15609232/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 14:00:07  来源:igfitidea点击:

How to add "Remember Me" to my app with passport

node.jsexpresspassport.js

提问by QingYun

I need a "Remember Me" checkbox when logging in like this. And I add a middleware before using passport

这样登录时,我需要一个“记住我”复选框。我在使用护照之前添加了一个中间件

app.use(function(req, res, next) {
  if (req.method == 'POST' && req.url == '/login') {
    if (req.body.rememberme) {
      req.session.cookie.maxAge = 1000 * 60 * 3;
    } else {
      req.session.cookie.expires = false;
    }
  }
  next();
});
app.use(passport.initialize());
app.use(passport.session());

I can not login when req.body.remembermeis true and the user is remembered when req.body.remembermeis false. I also tried connect-ensure-login and it still wrong.

req.body.rememberme为真时我无法登录,当req.body.rememberme为假时用户会被记住。我也试过connect-ensure-login,还是错了。

and another question: when should I delete the cookies in my database and how?

另一个问题:我应该什么时候删除数据库中的 cookie 以及如何删除?

:)

:)

Other code is exactly the same as the passport guide

其他代码与护照指南完全相同

route:

路线:

app.get('/', passport.authenticate('local', {
  failureRedirect: '/login'
}), function(req, res) {
  res.redirect('/user/home');
});
app.post('/login', passport.authenticate('local', {
  failureRedirect: '/login'
}), function(req, res) {
  res.redirect('/user/home');
});

sessions:

会议:

passport.serializeUser(function(user, done) {
  var CreateAccessToken = function() {
    var token = user.GenerateSalt();
    User.findOne({
      accessToken: token
    }, function(err, existingUser) {
      if (err)
        return done(err);
      if (existingUser) {
        CreateAccessToken();
      } else {
        user.set('accessToken', token);
        user.save(function(err) {
          if (err)
            return done(err);
          return done(null, user.get('accessToken'));
        })
      }
    });
  };
  if (user._id)
    CreateAccessToken();
});
passport.deserializeUser(function(token, done) {
  User.findOne({
    accessToken: token
  }, function(err, user) {
    if (err)
      return done(err);
    return done(err, user);
  });
});

and the strategie:

和策略:

passport.use(new LocalStrategy(function(userId, password, done) {
  User.findOne().or([{
    username: userId
  }, {
    email: userId
  }]).exec(function(err, user) {
    if (err)
      return done(err);
    if (!user) {
      return done(null, false, {
        message: 'Invalid password or username'
      });
    }
    if (user.Authenticate(password)) {
      return done(null, user);
    } else {
      return done(null, false, {
        message: 'Invalid password or username'
      });
    }
  });
}));


I noticed that Express will update the cookie only when hash value changed. so I have modified the code in the middleware

我注意到 Express 只会在哈希值更改时更新 cookie。所以我修改了中间件中的代码

app.use(function(req, res, next) {
  if (req.method == 'POST' && req.url == '/login') {
    if (req.body.rememberme) {
      req.session.cookie.maxAge = 1000 * 60 * 3;
      req.session._garbage = Date();
      req.session.touch();
    } else {
      req.session.cookie.expires = false;
    }
  }
  next();
});

now I can login with "Remember Me", but it only works on chromium and firefox on Ubuntu. I still can not login with the "Remember Me" checkbox on chrome and firefox on Win7 and Android.

现在我可以使用“记住我”登录,但它仅适用于 Ubuntu 上的 Chromium 和 firefox。我仍然无法在 Win7 和 Android 上的 chrome 和 firefox 上使用“记住我”复选框登录。

I checked response header when POST to "/login" on chrome on win7 and it had the same "Set-Cookie" field as it on Ubuntu, why it can not work?

我在 win7 上的 chrome 上 POST 到“/login”时检查了响应头,它与在 Ubuntu 上具有相同的“Set-Cookie”字段,为什么它不能工作?



Time is out of sync...so I post a extra time field.

时间不同步......所以我发布了一个额外的时间字段。

$('#login').ajaxForm({
  beforeSubmit: function(arr, $form, option) {
    arr.push({
      name: '__time',
      value: (new Date()).toGMTString()
    });
  }
});

and the "RememberMe" middleware:

和“记住我”中间件:

app.use(function(req, res, next) {
  if (req.method == 'POST' && req.url == '/login') {
    if (req.body.rememberme) {
      req.session.cookie.maxAge = moment(req.body.__time).add('m', 3) - moment();
      req.session._garbage = Date();
      req.session.touch();
    } else {
      req.session.cookie.expires = false;
    }
  }
  next();
});

回答by BOC

I had exactly the same problem as you. The following code works for me:

我和你有完全一样的问题。以下代码对我有用:

app.post("/login", passport.authenticate('local',
    { failureRedirect: '/login',
      failureFlash: true }), function(req, res) {
        if (req.body.remember) {
          req.session.cookie.maxAge = 30 * 24 * 60 * 60 * 1000; // Cookie expires after 30 days
        } else {
          req.session.cookie.expires = false; // Cookie expires at end of session
        }
      res.redirect('/');
});

回答by tcmoore

There is now a Passport strategy for adding Remember Me functionality writen by Jared Hanson.

现在有一个 Passport 策略,用于添加由 Jared Hanson 编写的“记住我”功能。

https://github.com/jaredhanson/passport-remember-me

https://github.com/jaredhanson/passport-remember-me

This works by issuing a unique remember-me token during every session that is consumed at the start of the next (invalidating it for future use.) As a result, this is likely to be a more secure solution.

这是通过在下一次开始时消耗的每个会话期间发出唯一的记住我令牌来工作的(使其无效以备将来使用。)因此,这可能是一个更安全的解决方案。

回答by Plato

Ensure that app.use(express.bodyParser())is placed above your middleware, as you are relying on req.body.rememberme

确保app.use(express.bodyParser())放置在您的中间件之上,因为您依赖req.body.rememberme