从客户端保护对集合的访问 [英] Securing access to collection from the client's side

查看:33
本文介绍了从客户端保护对集合的访问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a meteor app prototype that works well, but is very insecure as of now: I needed to display a list of matching users to the currently logged-in user. For starters, I decided to publish all users, limiting the fields to what I would need to filter the user list on the client side.

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

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

Then in my router, I would do a request to only show what I wanted on the client side:

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"数组中有我的用户的用户的照片上显示了一定的边框,使用这个客户端助手:

In the code above, I query all users who are not the current user and whose type correspond the current user's interest. I also display a certain border on the photos of users who have my user in their "profile.friends" array, using this client helper:

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 中,则只能在服务器端访问此信息.所以我决定我的下一个迭代是安全的.我会将我的查询从路由器文件移动到发布文件.这就是麻烦开始的地方...

Now this all worked great, but with this setup, every client can query every users and get their type, picture, list of friends and number of likes. If I was in an MVC, this info would only be accessible on server side. So I decided my next iteration to be a security one. I would move my query from the router file to the publications file. That's where trouble began...

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

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

(note that I still need to exclude the current user from the router query since the current user is always fully published)

这行得通,但是:

  1. 当我更改用户兴趣然后执行 Router.go('usersList') 时,用户列表不会更新.只有当我刷新浏览器时,我的列表才会根据用户的新兴趣更新.不知道为什么.
  2. 这个解决方案仍然发布用户的朋友,以显示我匹配的边框.我希望在我的发布查询中添加一个临时字段,如果用户在用户的朋友中,则将其设置为是",否则设置为否",但是……到目前为止还没有成功.我读到我可以使用聚合来实现这一点,但到目前为止还没有成功.此外,聚合不会返回发布所期望的游标.
  1. the user list does not get updated when I change the user interest and then do a Router.go('usersList'). Only when I refresh the browser, my list is updated according to the user's new interest. No idea why.
  2. this solution still publishes the users' friends in order to display my matching borders. I wish to add a temporary field in my publish query, setting it to "yes" if the user is in the user's friends and "no" otherwise, but... no success so far. I read I could use aggregate to maybe achieve that but haven't managed to so far. Also, aggregate doesn't return a cursor which is what is expected from a publication.

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

This problem makes me doubt about the praises about meteor being suitable for secure apps... This would be so easy to achieve in Rails or others!

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

As requested, here is the code I have so far for the transition of my "matching" check to the server:

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 循环中修改游标值.但它给出了我想要实现的目标:让客户端知道一个朋友是否匹配,而不是让客户端访问所有用户的朋友列表.(而且,避免在显示期间必须为每个用户执行一个请求以询问服务器此特定用户是否与此特定用户匹配)

Obviously this code doesn't work at all, since I cannot modify cursor values in a foreach loop. But it gives an idea of what I want to achieve: give a way to the client to know if a friend is matched or not, without giving access to the friend lists of all users to the client. (and also, avoiding having to do one request per each user during display to ask the server if this specific user matches this specific one)

推荐答案

您可以动态添加变换函数和修改光标文档流星集合.find

You can add a transform function and modify a cursor docs on the fly meteor Collection.find

这篇关于从客户端保护对集合的访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆