【问题标题】:Sails.js Policies, is there an OR operator to allow an action if one of a group of policies succeeds?Sails.js 策略,如果一组策略中的一个成功,是否有 OR 运算符允许执行操作?
【发布时间】:2013-09-23 10:31:39
【问题描述】:

在 config/policies.js 中配置 Sails 中的策略时,例如:

    ActivityController: {
        create: ['authenticated'],
        update: ['authenticated', 'isActivityOwner'],
        destroy: ['authenticated' ,'isActivityOwner']
    }

如果一组策略中的一个或多个成功,是否有任何功能可以让我授予对操作的访问权限,可能类似于:

    ActivityController: {
        create: ['authenticated'],
        update: ['authenticated', {or:['isActivityOwner', 'isAdmin']}],
        destroy: ['authenticated' ,'isActivityOwner']
    }

另外,是否可以创建复合策略,以便在一个策略中检查一个或多个其他策略?

如果这两个选项看起来都不是很好的解决方案,您能否提出一种被认为是更好的做法的方法?

如果这有点明显,请原谅我,但总的来说我对风帆和节点还很陌生,提前感谢您的帮助!

【问题讨论】:

    标签: policy sails.js


    【解决方案1】:

    我还没有在风帆政策中找到对运营商的任何官方支持,但这就是我正在做的事情。

    ActivityController: {
        update: ['authenticated', 'orActivityOwner', 'orAdmin', orPolicy],
    }
    

    orActivityOwnerorAdmin 都返回 next(),就好像它们是有效的一样。但他们也为会话变量设置了一个布尔值。请记住,策略是从左到右执行的。我在末尾添加了一个orPolicy,然后它将评估我们会话变量的状态。

    【讨论】:

    • 这是一个可用的解决方法,但我认为它有点混乱。如果可以为对象提供像{ operator: 'OR', policies: ['ActivityOwner','Admin']} 这样的运算符,也许会更好。我认为这会更灵活。我会看一下代码,也许会问 Sails 团队是否对这种方法感兴趣。不过感谢您的解决方法!
    • 出色的解决方法。您还可以选择绝对需要的部分,例如:isLoggedIn 您可以直接点击 res.redirect ,并且任何其他“或”策略不断通过,直到它点击 orPolicy 进行评估。
    • 您建议强制在策略目录中提供大量文件。对于每项权利,您必须创建或、与、是。因此,例如,如果您有管理员和用户,它将拥有 6 个单独的权限。
    • 很好的解决方案@Travis
    【解决方案2】:

    查看sails-must:

    ActivityController: {
        create: 'authenticated',
        update: ['authenticated', must().be.the.owner.or.be.a.member.of('admins')],
        destroy: ['authenticated', must().be.the.owner]
    }
    

    【讨论】:

      【解决方案3】:

      我创建了一个可以向策略添加参数的 Sails 挂钩:
      https://github.com/mastilver/sails-hook-parametized-policies

      我设置了一个示例,其中定义了 or 策略:

      module.exports = function(firstPolicy, secondPolicy){
      
          return function(req, res, next){
      
      
              var fakeRes = {};
      
              for(var i in res){
                  if(i === 'forbidden'){
                      // override the functions you want the `or` factory to handle
                      fakeRes[i] = function(){
                          secondPolicy(req, res, next);
                      };
                  }
                  else{
                      fakeRes[i] = res[i];
                  }
              }
      
      
              firstPolicy(req, fakeRes, next);
          }
      }
      

      你可以这样使用:

      ActivityController: {
              create: ['authenticated'],
              update: ['authenticated', 'or(isActivityOwner, isAdmin)'],
              destroy: ['authenticated' ,'isActivityOwner']
          }
      

      【讨论】:

      【解决方案4】:

      只是为了完成上一个答案,这就像一个魅力:


      信息片段

      但他们也为会话变量设置了一个布尔值

      我自己更喜欢将此布尔值设置为 req 对象,即:

      • 更加语义化(为请求授予或不授予资源访问权限,而不是整个会话
      • 不需要我手动重置此变量 (我应该补充一点,如果您确实想使用 @Travis 解决方案中的会话,则最后一个 orPolicy 策略必须重置(甚至取消设置)variable 以保护下一个请求)

      我的实现

      config/policies.js

      MyController: {
        find: ['orIsTest1', 'orIsTest2', 'protectedResourceGranted']
      }
      

      api/policies/orIsTest1.js

      module.exports = function(req, res, next) {
        req.protectedResourceGranted = req.protectedResourceGranted || WHATEVERFIRSTTEST;
      
        return next();
      };
      

      api/policies/orIsTest2.js

      module.exports = function(req, res, next) {
        req.protectedResourceGranted = req.protectedResourceGranted || WHATEVERSECONDTEST;
      
        return next();
      };
      

      api/policies/protectedResourceGranted.js

      module.exports = function(req, res, next) {
        if(req.protectedResourceGranted) {
          return next();
        }
      
        return res.forbidden();
      };
      

      注意:只是回答,因为我没有足够的声誉来发表评论。

      【讨论】:

        【解决方案5】:

        这里的其他答案效果很好,但这是一个我觉得更简洁的实现。

        您可以修改现有策略以在 AND/OR context,同时几乎不会改变他们的行为。然后创建一个复合策略(如 OP 建议的那样)来检查修改后的现有策略。

        config/policies.js 带有示例控制器和策略:

        AdminController: {
          adminDashboard: 'isAuthenticated',
        },
        
        ItemController: {
          findOne: 'isPublishedOrIsAuthenticated'
        }
        

        api/policies/isAuthenticated.jsapi/policies/isPublished.js 以及您想用作 AND/检查:

        如果 next 设置为 true 布尔值(而不是回调),只需返回 truefalse,然后策略通常会返回 next()res.notFound() 等。

        module.exports = function(req, res, next) {
          // do some checking
          if(next === true) return true; // or return false
          return next();
        };
        

        请注意,我们需要在这里使用triple-equals 符号。

        api/policies/isPublishedOrIsAuthenticated.js

        module.exports = function(req, res, next) {
          var isPublished = require('./isPublished.js');
          var isAuthenticated = require('./isAuthenticated.js');
        
          // This reads like what we are trying to achieve!
          // The third argument in each call tells the function to return a boolean
          if(isPublished(req, res, true) || isAuthenticated(req, res, true))
            return next();
        
          return res.notFound();
        };
        

        【讨论】:

        • 有人知道比require 更好的手动调用策略的方法
        猜你喜欢
        • 2022-12-21
        • 1970-01-01
        • 2021-12-15
        • 2017-12-30
        • 1970-01-01
        • 2023-01-17
        • 1970-01-01
        • 2010-11-02
        • 2021-01-07
        相关资源
        最近更新 更多