【问题标题】:Securing access to collection from the client's side确保从客户端访问集合
【发布时间】:2014-07-15 08:14:24
【问题描述】:

我有一个运行良好的流星应用原型,但目前非常不安全:我需要显示与当前登录用户匹配的用户列表。对于初学者,我决定发布所有用户,将字段限制为过滤客户端用户列表所需的字段。

Meteor.publish('users', function () {
  return Meteor.users.find({}, {
    fields: {
      'profile.picture': 1,
      'profile.likes': 1,
      'profile.friends': 1,
      'profile.type': 1
    }
  });
});

然后在我的路由器中,我会请求只在客户端显示我想要的内容:

Router.map(function() {
  this.route('usersList', {
    path: '/users',
    waitOn: function () {
      return Meteor.subscribe('users');
    },
    data: function () {
      var user = Meteor.user();
      return {
        users: Meteor.users.find({ $and: [
            {_id: {$ne : user._id}},
            {'profile.type': user.profile.interest}
          ]})
      };
    }
  });
});

在上面的代码中,我查询了所有不是当前用户且类型对应当前用户兴趣的用户。我还在“profile.friends”数组中有我的用户的用户的照片上显示了一定的边框,使用这个客户端助手:

Template.userItem.helpers({
  getClass: function(userId) {
    var user = Meteor.user();
    var lookedup = Meteor.users.findOne({_id: userId});
    if ($.inArray(user._id, lookedup.profile.friends) !== -1)
      return "yes";
    return "no";
  }
});

现在这一切都很好,但是通过这个设置,每个客户都可以查询每个用户并获取他们的类型、图片、朋友列表和喜欢的数量。如果我在 MVC 中,则只能在服务器端访问此信息。所以我决定我的下一个迭代是安全的。我会将查询从路由器文件移动到发布文件。这就是麻烦开始的地方......

Meteor.publish('users', function () {
  var user = Meteor.users.findOne({_id: this.userId});
  var interest =  user.profile.interest;
  // retrieve all users, with their friends for now
  allUsers = Meteor.users.find({ $and: [
      {'_id': {$ne: user._id}},
      {'profile.type':interest}
    ]},
    { fields: {'profile.picture': 1, 'profile.friends': 1}}
  );
  return allUsers;
});

在路由器中:

Router.map(function() {
  this.route('usersList', {
    path: '/users',
    waitOn: function () {
      return Meteor.subscribe('users');
    },
    data: function () {
      var user = Meteor.user();
      return {users: Meteor.users.find({_id: {$ne : user._id}})};
    }
  });
});

(请注意,我仍然需要从路由器查询中排除当前用户,因为当前用户始终是完全发布的)

这可行,但是:

  1. 当我更改用户兴趣然后执行Router.go('usersList') 时,用户列表没有更新。只有当我刷新浏览器时,我的列表才会根据用户的新兴趣进行更新。不知道为什么。
  2. 此解决方案仍会发布用户的好友以显示我匹配的边框。我希望在我的发布查询中添加一个临时字段,如果用户在用户的朋友中,则将其设置为“是”,否则设置为“否”,但是......到目前为止没有成功。 I read I could use aggregate to maybe achieve that 但到目前为止还没有成功。此外,聚合不会返回出版物所期望的游标。

这个问题让我怀疑流星适用于安全应用程序的赞美......这在Rails或其他人中很容易实现!

编辑:根据要求,这是我迄今为止将“匹配”检查转换为服务器的代码:

Meteor.publish('users', function () {
  var user = Meteor.users.findOne({_id: this.userId});
  var interest =  user.profile.interest;
  // retrieve all users, with their friends for now
  allUsers = Meteor.users.find({ $and: [
      {'_id': {$ne: user._id}},
      {'profile.type':interest}
    ]},
    { fields: {'profile.picture': 1, 'profile.friends': 1}}
  );
  // ------------- ADDED ---------------
  allUsers.forEach(function (lookedup) {
    if (_.contains(lookedup.profile.friends, user._id))
      lookedup.profile.relation = "yes";
    else
        lookedup.profile.relation = "no";
    lookedup.profile.friends = undefined;
    return lookedup;
  });
  // ------------- END ---------------
  return allUsers;
});

显然这段代码根本不起作用,因为我无法在 foreach 循环中修改游标值。但它给出了我想要实现的目标:让客户知道是否匹配朋友,而不向客户提供所有用户的朋友列表的访问权限。 (而且,避免在显示期间必须为每个用户执行一个请求,以询问服务器该特定用户是否与该特定用户匹配)

【问题讨论】:

  • 1.是预期的行为,因为服务器上的发布代码是非反应性的。这篇博文可能会对您有所帮助:discovermeteor.com/blog/reactive-joins-in-meteor 2. 实施起来应该不会太难。我认为检查用户是否在当前用户的朋友列表中而不是相反(如果友谊是双向的)是一个好主意。您可以发布您尝试过的代码吗?
  • 对于 2. 它实际上是一个“匹配”系统,为了清楚起见我对其进行了简化(我认为问题已经够复杂了)。所以我需要检查用户是否在其他用户的朋友中,而不是让他访问这个用户的整个朋友列表。我并没有真正“尝试”我认为可行的东西,而是反复进行。无论如何我都会放代码;)

标签: security meteor publish-subscribe


【解决方案1】:

您可以添加转换函数并即时修改光标文档 meteor Collection.find

【讨论】:

    猜你喜欢
    • 2015-09-30
    • 2014-05-10
    • 2016-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多