Express cookieSession 和 Mongoose:如何让 request.session.user 成为 Mongoose 模型? [英] Express cookieSession and Mongoose: how can I make request.session.user be a Mongoose model?

查看:24
本文介绍了Express cookieSession 和 Mongoose:如何让 request.session.user 成为 Mongoose 模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

创建新用户帐户时,我创建 newUser,一个 Mongoose 模型实例,如下所示:

When a new user account is created, I create newUser, a Mongoose model instance that looks like:

_events: Object
errors: undefined
isNew: false
save: function () {
arguments: null
caller: null
_doc: Object
  name: 'Joe Smith'
...

对象的实际数据在 _doc 属性中,尽管存在 getter 和 setter,因此您可以运行:

The actual data for the object is in the _doc property, though getters and setters exist so you can run:

user.name = 'Jane Doe' 

这样就可以正常工作了.我跑:

and that will work fine. I run:

request.session.user = newUser;

将用户保存到会话中.到目前为止,一切都很好.

To save the user to the session. So far, so good.

然而,在随后的请求中,request.session.user 似乎只是_doc 中的东西.例如:

However, in subsequent requests, request.session.user seems to be only the stuff in _doc. Eg:

name: 'Joe Smith'

这很好,但这意味着我无法运行例如 request.session.user.save() 来保存更改.

Which is nice, but that means I can't run eg, request.session.user.save() to save changes.

我可以简单地制作一些中间件来查找与数据关联的用户.但我想更多地了解 Express 和 Mongoose 在这里做什么.

I could simply make some middleware to look up the user associated with the data. But I'd like to know more about what Express and Mongoose are doing here.

如何让 request.session.user 成为 Mongoose 模型?

How can I make request.session.user be a Mongoose model?

更新:我当前的中间件黑客:

Update: my current middleware hack:

// Use as a middleware on routes which need users
// TODO: only needed due to request.session.user being saved weirdly
var rehydrateUser = function(request, response, next) {
  if ( request.session.user ) {
    var hydrated = request.session.user.save
    if ( ! hydrated ) {
      console.log('Rehydrating user...');
      models.User.findOne({ somefield: request.session.user.somefield }, function (err, user) {
        if ( err ) {
          request.session.error = 'User not found in DB!';
          request.redirect('/');
        } else {
          request.session.user = user;          
          console.log('Rehydrated user! All repos already being monitored.');
          next();
        }
      })
    } else {
      next();
    }
  } else {
    console.log('No user in session')
    next();
  }
}

推荐答案

Express 会话被存储为单独的存储,并且对可以存储在那里的内容有限制.它不能存储原型数据(方法).把它看成更像是 key<>value 存储.

Express session is stored as separate storage and has limitations to what can be stored there. It cannot store prototype data (methods). Look at it more like key<>value storage.

这样做的原因是session可以存储在任何地方(差不多),比如:进程内存;数据库(mongodb);Redis;等

Reasons for this is that session can be stored anywhere (pretty much), such as: process memory; databases (mongodb); redis; etc.

因此,一旦您将任何内容放入会话对象并且请求完成,express 将获取会话数据,解析它并像纯对象一样粘贴到会话存储中.默认情况下它是进程内存,但如前所述 - 可以是任何其他存储.

Because of this, once you put anything in session object and request is finished, express will take session data, parse it and stick into session store just as pure object. By default it is process memory, but as mentioned before - can be any other storages.

因此,当下一个 http 请求发生时,会话中间件将尝试使用请求头中的 cookie(如果使用)数据恢复会话,并要求会话存储提供数据.因为它已经格式化 - 它不会有 .prototype 的东西,而只有数据(objectarraystringnumber,以及其他简单的东西).

So when next http request happens, session middleware will try to restore session using cookie (if it is used) data in request headers, and will ask session storage to provide data back. As it is already formatted - it will not have .prototype stuff but just data (object, array, string, number, and other simple stuff).

因此您需要再次使用该数据创建模型.
你可以通过 express 中的中间件来完成.所以在 app.configure 定义 session 之后直接你可以这样做:

So you need to create Model out of that data again.
You can do by middleware in express. So in app.configure straight after defining session you can do this:

app.use(function(req, res, next) {
  if (req.session && req.session.user) {
    req.session.user = new UserModel(req.session.user);
  }
  return next();
});

这将检查会话是否与用户一样被定义.然后将根据该数据重新创建猫鼬模型.

This will check if session is defined as well as user. And then will recreate mongoose model out of that data.

正如这里在评论中提到的 - 您不应该将用户数据存储在会话中,因为这会由于数据所有权的责任划分而导致不一致.所以只存储用户的ID,然后使用中间件从数据库加载它.

As mentioned here in comments - you should not store user data in session as it will lead to inconsistencies due to split of responsibilities over ownership of data. So store just ID of user, and then using middleware load it from Database.

app.use(function(req, res, next) {
  if (req.session && req.session.userID) {
    UserModel.findById(req.session.userID, function(err, user) {
      if (!err && user) {
        req.user = user;
        next();
      } else {
        next(new Error('Could not restore User from Session.'));
      }
    });
  } else {
    next();
  }
});

在你可以创建中间件来检查用户是否登录之后:

After you can create middleware to check if user is logged in:

function userRequired(req, res, next) {
  if (req.user) {
    next();
  } else {
    next(new Error('Not Logged In');
  }
}

并像这样使用它:

app.get('/items', userRequired, function(req, res, next) {
  // will only come here if user is logged in (req.user !== undefined)
});

这篇关于Express cookieSession 和 Mongoose:如何让 request.session.user 成为 Mongoose 模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆