【问题标题】:sails.js Use session param in modelSails.js 在模型中使用会话参数
【发布时间】:2014-05-16 04:47:01
【问题描述】:

这是this question的扩展。

在我的模型中,每个模型都需要在创建时设置 companyId,并且每个模型都需要通过同一会话持有的 companyid 过滤模型。

对于sails.js,我已阅读并理解该会话在模型中不可用,除非我使用控制器注入它,但是这将需要我使用非常非常重复的东西对我的所有控制器/动作进行编码。不幸的。

我喜欢sails.js 并想进行转换,但谁能向我描述一个更好的方法?我希望我只是错过了一些东西。

【问题讨论】:

    标签: node.js sails.js


    【解决方案1】:

    所以,如果我的理解正确,您希望在控制器中避免大量这样的代码:

    SomeModel.create({companyId: req.session.companyId, ...})
    SomeModel.find({companyId: req.session.companyId, ...})
    

    很公平。可能你担心companyId以后会被重命名,或者需要进一步处理。如果您使用自定义控制器操作,最简单的解决方案是为您的模型创建接受请求作为参数的类方法:

    SomeModel.doCreate(req, ...);
    SomeModel.doFind(req, ...);
    

    另一方面,如果您在 v0.10.x 上并且可以将蓝图用于某些 CRUD 操作,您将受益于override the blueprints with your own code 的功能,因此您的所有创建和查找都会自动使用companyId 来自会话。

    如果您来自非 Node 背景,这可能都会引起一些令人头疼的问题。 “为什么你不能让会话随处可用?”你可能会问。 “就像他们在 PHP 中所做的那样!”

    原因是 PHP 是无状态——每个传入的请求本质上都是应用程序的一个新副本,内存中没有任何内容在请求之间共享。这意味着任何全局变量仅在单个请求的生命周期内有效。那个美妙的$_SESSION 哈希是你的,也是你自己的,一旦请求被处理,它就会消失。

    与 Node 应用相比,后者本质上在单个进程中运行。您设置的任何全局变量都将在传入的每个请求之间共享,并且由于请求是异步处理的,因此无法保证一个请求会在另一个请求开始之前完成。所以很容易出现这样的情况:

    1. 请求 A 进来了。
    2. Sails 获取请求 A 的会话并将其存储在全局 $_SESSION 对象中。
    3. 请求 A 调用 SomeModel.find(),后者异步调用数据库
    4. 当数据库发挥作用时,请求 A 放弃了对节点线程的控制
    5. 请求 B 进来了。
    6. Sails 获取请求 B 的会话并将其存储在全局 $_SESSION 对象中。
    7. 请求 B 放弃对线程的控制以执行其他异步调用。
    8. 请求 A 返回其数据库调用的结果,并从 $_SESSION 对象中读取一些内容。

    您可以在这里看到问题——请求 A 现在有错误的会话数据。这就是会话对象存在于请求对象中的原因,也是为什么需要将它传递给任何想要使用它的代码的原因。过分努力地规避这一点,必然会带来麻烦。

    【讨论】:

    • 这是你能得到的最完整的答案。
    • Scott - 你能指出一些显示这些蓝图覆盖的文档吗?我正在寻找,但可能还不够努力。
    • 测试版的文档仍然不完整,但answer I linked to 应该可以帮助您入门。
    • 你认为我可以在模型执行之前将 companyid 添加到 req.params 中吗?如果是这样,你认为我可以在哪里添加?我想我正在寻找某种可以添加 companyId 的请求拦截器。 (这可能偏离主题,我应该开始一个新问题)
    • 找到了解决方案。在所有控制器的策略中,我添加以下 req.query.companyId = req.session.user.companyId;所有默认模型在创建/过滤时都会查看查询。所以开箱即用,一切都可以使用这个简单的代码。希望这是一种有效的方式。
    【解决方案2】:

    我能想到的最佳选择是利用 JS,并制作一些全局可访问的功能。

    但它会有代码味道:(

    【讨论】:

      【解决方案3】:

      我更喜欢制定一个在 body.param 中添加 companyId 的策略,如下所示:

          // Needs to be Logged
          module.exports = function(req, res, next) {
              sails.log.verbose('[Policy.insertCompanyId() called] ' + __filename);
      
              if (req.session) {
                  req.body.user = req.session.companyId; 
                       //or something like AuthService.getCompanyId(req.session);
                  return next();
              }
      
              var err = 'Missing companyId'; 
              //log ...
              return res.redirect(307, '/');
          };
      

      【讨论】:

        猜你喜欢
        • 2014-01-26
        • 2015-08-03
        • 2015-01-26
        • 2016-05-12
        • 2017-03-04
        • 1970-01-01
        • 2014-10-01
        • 1970-01-01
        相关资源
        最近更新 更多