我应该在没有数据库操作的方法中使用Meteor方法存根吗?

时间:2016-04-07 13:35:22

标签: javascript meteor

我知道我可以使用方法存根来模拟数据库操作,然后才真正在服务器上运行,如@Akshat解释in this excellent answer

我想知道我是否可以而且应该使用存根来确保用户有权在不涉及任何数据库操作时执行操作(例如显示编辑按钮)。

请注意,我不想使用alanning:roles包,我想了解它是如何工作的,以及是否可以按如下方式完成:

假设我想检查管理员权限。每个用户文档都有一个roles字符串数组字段,用于存储用户的全局权限,即useradminsuperadmin等。

我在Users文件夹中声明我的lib集合,可供客户端和服务器使用:

let Users = Meteor.users
export default Users

我创建了一个方法存根来检查客户端上的管理员权限(它位于客户端文件夹中):

Meteor.methods({ 
  UserIsAdmin = function () {
    console.log(this.isSimulation) //Will be true
    let user = Users.findOne({_id: Meteor.userId()})
    return !!(user && user.roles && user.roles.indexOf('admin') != -1)
  }
});

在服务器文件夹中,我将创建一个真正的方法来调用下面写的内部服务器函数(请注意,在这种情况下,我可以将userId设置为参数):

import Users from '/imports/user/lib/user_collection.js'

Meteor.methods({ 
  UserIsAdmin = function () {
    console.log(this.isSimulation) //Will be false
    return Users.isAdmin()
  }
});

Users.isAdmin = function (userId=Meteor.userId()) {
  var user = Users.findOne({_id: userId})
  return !!(user && user.roles && user.roles.indexOf('admin') != -1)
};

现在假设我的UI上有一个编辑按钮,我会根据UserIsAdmin方法的结果显示它。以下是问题:

  1. 如果用户管理某种方式更改角色数组或弄乱方法,我假设按钮将一直显示,直到服务器应答方法调用,对吧?但它在延迟方面没有帮助,无论如何都要加载UI。
  2. 相同的情况(用户不是管理员,而是在本地修改了他的role数组),但我们在加载路由之前检查方法:路由及其UI将被加载,对吧?没有回滚?当然,由于发布不会返回任何内容,因此不会填充UI。
  3. 我拒绝允许/拒绝规则中的每个插入/更新/删除,因此我可以认为用户无法修改自己的文档。如果是这样,是否值得花时间为没有进行任何数据库操作的方法编写方法存根?我的意思是,它不是保护UI的可靠方法(参见上面的问题2),无论如何都不会发布数据。是否有一种情况,除了db操作,编写方法存根有意义吗?

2 个答案:

答案 0 :(得分:1)

我不认为这在额外的安全性方面真的会给你带来太大的好处。您已经基于管理员权限隐藏了管理员UI,然后您在服务器端阻止了管理员的任何管理员操作。据推测,您也没有将管理员数据发布给非管理员。

即使您让用户很难查看管理员屏幕,他们仍然可以看到创建它的源以及它调用的方法。他们最终可以对管理系统控制的内容进行逆向工程。

如果将管理界面捆绑在一起并提供给非管理员用户,则完全可以完全隐藏它。常见的模式是在单独的主机或端口上创建第二个管理应用程序,只能由管理员访问。管理员应用程序连接到同一个mongo数据库,因此可以控制消费者应用程序的哪些用户可以执行。

您给攻击者的一些最大线索是您使用的角色名称(admin,superadmin)。搜索已发布的“管理员”流星代码太简单,并获得有关正在发生的有趣事情的线索。方法名称也很容易被挑选出来,因为它们不会被缩小和混淆,请仔细选择。

答案 1 :(得分:1)

您的代码取决于Meteor方法的返回值,但您有一个客户端和服务器端返回值。幸运的是,它很好地定义了你会得到哪一个:

  • 如果您的Meteor.call()中有回调,则call函数不返回任何内容,并且将使用服务器端返回值调用回调函数。 / LI>
  • 如果您的Meteor.call()没有回调,那么您将同步获得客户端返回值。

无论哪种方式,您只会看到其中一个返回值。它不像订阅,其值将以某种方式稍后同步。请参阅此处的文档:http://docs.meteor.com/#/full/meteor_call

并回答你的问题:

  1. 取决于您是否使用回调。如果没有,则显示管理员UI,并且不会回滚。
  2. 与1相同。
  3. 您应始终假设用户能够并且愿意修改所有客户端数据。拒绝规则根本不会改变它们,它们只会停止将这些更改传播到服务器。
  4. 除了数据库操作之外,您可以使用服务器端方法调用执行各种操作,例如使用密钥访问第三方REST API,启动后台操作等。

    alanning:roles包的工作方式是通过订阅保持同步的roles集合。他们的Roles.userIsInRole函数不是Meteor方法,而是查询此集合的简单函数调用。