如何使用Passport和node.js

时间:2017-05-31 16:06:17

标签: node.js mongodb express passport.js

我对后端开发很新......

使用我的API我希望能够显示用户列表,并指出他们当前是否已登录。我使用passportjson web token进行了基本身份验证工作 我希望获得当前登录的用户。 我希望能够检索用户列表并查看他们是否已登录。

像这样:

var users = Users.find({});
// console.log(users) output:
{
  name: 'foo'
  password: ...
  isLoggedIn: false
},
{
  name: 'bar'
  password: ...
  isLoggedIn: true
},
{
  name: 'baz'
  password: ...
  isLoggedIn: false
}
如果用户当前已登录,则

isLoggedIn将设置为true,如果不是,则设置为false

我该怎么做?谢谢!

1 个答案:

答案 0 :(得分:2)

听起来您想要做的是根据登录/注销事件更新MongoDB数据库。为此,您可以使用mongoose之类的东西来处理Node后端,以便轻松访问MongoDB中的数据库。

您可以在使用npm install mongoose进行安装后添加mongoose,如下所示:

var mongoose = require('mongoose');
var User = mongoose.model('User');

请注意,User对应于您为存储用户信息而创建的任何架构。

假设您有某种router对象来处理请求,您可以为/logout/login构建路由处理程序,并使用导入的mongoose User模型来检索并修改特定的用户对象如下:

// whenever user goes to '/login' (you can have, say, your 'login' button make a request to this URL

router.get('/login', function(req,res) {
   // your authentication here; passport stores the currently authenticated user in req.user 
   var username = req.user.name; // here we assume the username is stored as 'name' as you have in your code but change this based on your schema
   User.findOne({name: username}, function(err, user, data) {
      if(err) res.send(err);
      user.isLoggedIn = true;
      user.save(function (err) {
         if (err) {
            console.log(err);
         } else {
            // redirect to some page here maybe
         }
      });
   });
});

// whenever user goes to '/logout' (you can have a logout button make a request to this URL

router.get('/logout', function(req,res) {
   // currently authenticated user is still in req.user
   var username = req.user.name;
   User.findOne({name: username}, function(err, user, data) {
      if(err) res.send(err);
      user.isLoggedIn = false;
      user.save(function (err) {
         if (err) {
            console.log(err);
         } else {
            // redirect to login/register page maybe
         }
      });
   });
});

总结一下这段代码会做什么:

  • 根据用户访问的网址,我们的路由处理程序将根据名称(用户名)从我们的数据库中获取一个正确的唯一User对象

  • 它会通过访问req.user的用户名属性来实现,该属性对应于当前经过身份验证的Passport用户,对于所有用户来说也是如此

  • 更新我们用于跟踪登录状态的字段(isLoggedIn

  • 然后保存更改,之后我们更新状态以反映用户是否已登录,因此我们现在可以重定向到其他页面或显示其他内容

最后,您可以检索所有用户的列表,类似于您的代码,如下所示:

User.find({}, function(err, users, data) {
   // all users from your database are in `users`
   console.log(users);
});

编辑过期的会话:

因此,要跟踪过期的会话,因为您正在使用Passport,理论上需要功能来通过某种事件/回调/消息等发出信号,此时会话被视为无效。现在这很难监控,而且根据我对Passport的经验,这样的东西并没有在所有身份验证策略中实现,并且可能因开发人员使用的策略而异(例如,如果浏览器窗口关闭,请考虑基于Passports身份验证策略,或只是浏览器,它可能会立即破坏会话的cookie,我们的服务器无法知道它)。我建议检查Passport提供的所有身份验证策略,以防有更好的here

现在,如果您想添加功能以自行跟踪用户的被动登录/注销状态,您可以使用与cookie相关的内容。同样,不一定要使用,但这里有一些方便的Express模块​​:cookie-parsercookie-session

然后,您可以使用cookie-parser

设置和读取此类Cookie
var express      = require('express');
var cookieParser = require('cookie-parser');

var app = express();
app.use(cookieParser());

在用户通过身份验证后,您可以将此代码放在某处:

// cookies are stored here
console.log(req.cookies); 

// configure your cookie
var options = {
    expires: 1000 * 60 * 60, // expires after one hour
    httpOnly: true
}

// Set cookie
res.cookie('session', ('user-' + req.user.name), options);

然后,在客户端检查该cookie是否在某个时间间隔内持续有效,如果它已过期Date.now() > cookie.expires,则向/logout发出GET请求,然后注销用户(目前仍经过身份验证)通过更新MongoDB和所有。

但是,由于这需要建立一个基本模拟过期会话的机制,我建议使用类似于超时的东西,这将更容易实现。只需注意,这有点类似于您可能遇到的某些页面上的机制,其中您会弹出一个“由于不活动而将被注销”的弹出窗口。在您的main.js或任何客户端脚本中定义一个继续超时的函数,除非用户执行某些操作。

var inactivity = function () {
   var t;

   // user doing something on your page, so keep resetting time counter when events happen
   document.onmousemove = resetTimer;
   document.onkeypress = resetTimer;

   // this is a callback function that will get called once a time-out countdown is done
   function timeOut() {
      // make a request to '/logout' here and logout the current user (you still will have access to req.user from Passport)
      // also can redirect from back-end route handler to the login page for instance
   }

   // this gets called whenever an event happens, resetting the counter of sorts
   function resetTimer() {
       t = 0;
       t = setTimeout(timeOut, 1000 * 60 ) // set this to however long you should wait to log out your user time (in milliseconds)
   }
 };

基本上,这种方法可以让你自己使会话自动失效,这意味着你可以更好地控制更新数据库的状态并将用户注销。

希望这有帮助!