当前位置: 首页 > 面试题库 >

Express cookieSession和Mongoose:如何使request.session.user成为Mongoose模型?

施兴言
2023-03-14
问题内容

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

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

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

user.name = 'Jane Doe'

这样就可以了。我跑:

request.session.user = newUser;

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

但是,在后续请求中,request.session.user似乎只是_doc中的内容。例如:

name: 'Joe Smith'

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

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

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

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

// 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存储。

这样做的原因是会话可以存储在任何地方(很多),例如:进程内存;数据库(mongodb); 重做 等等

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

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

因此,您需要再次根据该数据创建模型。
您可以通过中间件快速完成。因此,app.configure在定义后,session 您可以直接执行以下操作:

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

这将检查是否定义了会话以及用户。然后将根据该数据重新创建猫鼬模型。

如此处的注释中所述-您不应在会话中存储用户数据,因为由于责任与数据所有权的划分会导致不一致。因此,仅存储ID用户,然后使用中间件从数据库加载它。

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();
  }
});

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

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)
});


 类似资料:
  • 另一个问题询问如何从现有的字符串表示形式创建。在本例中,您已经有了ID的字符串表示形式--它可能是也可能不是普遍唯一的--并且您正在将其解析为。

  • 对我来说,这似乎是如此基本和简单,但我在网上没有找到任何东西。 有许多关于如何获得JSON模式的示例,也有许多如何从以下对象创建mongoose模式的示例: 如果我试图直接放置JSON模式,我会得到一个错误 但是我在网上找不到从一种类型到另一种类型的转移。 以前有人有这个问题吗?

  • 问题内容: 我正在尝试使用Mongoose将AngularJS与MongoDB连接。我想传递控制器要使用的模型,所以我可以$ scope到数据。我不确定是否必须设置Angular Service,如果可以,您是否可以指出正确的方向。谢谢。 概述: 模型: 控制器: 问题答案: 您将需要一个临时步骤。直接从Angular转到Mongo是行不通的。如果您想要Mongo的通用REST接口,可以使用Ang

  • Mongoose 是设计用于异步环境的 MongoDB 对象模型工具,支持 promises 和 callbacks。 概述 连接到 MongoDB 首先需要定义一个连接。如果应用仅使用一个数据库,则使用mongoose.connect。如果需要创建其他连接,请使用mongoose.createConnection。 connect 和 createConnection都使用 mongodb://

  • 问题内容: 据我所知,方法是,那是,并且也喜欢,但它们不是存储在数据库中。 但是,我想知道那是和之间的唯一区别。还有其他我想念的东西吗? 问题答案: 实例方法,静态方法或虚拟方法均未存储在数据库中。方法与虚拟函数之间的区别在于,虚拟函数的访问方式类似于属性,方法的调用方式类似于函数。实例与静态实例与虚拟实例之间没有区别,因为在类上具有可访问的虚拟静态属性是没有意义的,但在类上具有某些静态实用程序或

  • 问题内容: 我正在尝试在MongoDB中更新实例化模型(“地方”-我知道它可以在其他路线中使用),并且花了一段时间尝试正确地做到这一点。我还试图重定向回查看“位置”的页面,以查看更新的属性。 节点v0.4.0,Express v1.0.7,Mongoose 1.10.0 架构: 控制器/路线: }); 我尝试了多种方法,但似乎无法理解。 另外,我不是如何声明三个{name,capital和cont