制作投票系统安全Meteor.Methods

时间:2016-02-18 16:25:28

标签: meteor meteor-methods

我正在尝试实施一个安全的投票系统,并且无法通过客户端控制台中的Meteor.call()进行更改。如果他们登录,每个人都可以上下调整一些帖子。但每个用户和帖子只需一次。

Ony我的客户端我有这样的事情:

Template.postArgument.events({
 'click .yes':function() {
       if(Meteor.user()) {
        var postId = Arguments.findOne({_id:this._id})
        var currentArgumentId = this._id;
        if($.inArray(Meteor.userId(), postId.votedUp) ===-1) {
          if($.inArray(Meteor.userId(), postId.votedDown) !==-1) {
            Meteor.call('argumentVoteYes',currentArgumentId);
          } else {
            Meteor.call('argumentVoteYesElse',currentArgumentId);
          } 
        } else {
          Meteor.call('argumentVoteYesElseElse',currentArgumentId);
        }
      }
    }}
)};

在我的服务器上:

    Meteor.methods({
    'argumentVoteYes':function(currentArgumentId){
        Arguments.update(currentArgumentId, {
            $pull: {votedDown: Meteor.userId()},
            $inc: {score: 2 },
                $addToSet: {votedUp: Meteor.userId() }
              });
      },
      'argumentVoteYesElse':function(currentArgumentId){
        Arguments.update(currentArgumentId, {
            $inc: {score: 1 },
            $addToSet: {votedUp: Meteor.userId() }
              });
      },
      'argumentVoteYesElseElse':function(currentArgumentId){
        Arguments.update(currentArgumentId, {
            $inc: {score: -1 },
            $pull: {votedUp: Meteor.userId()}
            });
      }
    'argumentVoteNo':function(currentArgumentId){
    Arguments.update(currentArgumentId, {
        $pull: {votedUp: Meteor.userId()},
        $inc: {score: -2 },
        $addToSet: {votedDown: Meteor.userId() },
        });
  },
  'argumentVoteNoElse':function(currentArgumentId){
    Arguments.update(currentArgumentId, {
        $inc: {score: -1 },
        $addToSet: {votedDown: Meteor.userId() },
        });

  },
  'argumentVoteNoElseElse':function(currentArgumentId){
    Arguments.update(currentArgumentId, {
        $inc: {score: 1 },
        $pull: {votedDown: Meteor.userId()}
        }); 
  },
    });

问题是我如何获得这种安全性,例如,如果有人呼叫Meteor.call('argumentvoteYes', "someID" , {$inc: {score:2}});它将增加2分。如果用户两次调用,则投票将增加4.有没有办法做到这一点安全的方式?

3 个答案:

答案 0 :(得分:1)

您需要检查用户是否在服务器上的votedUp / down数组中。您拥有逻辑权限客户端,因此在服务器上进行实际更新之前,只需应用相同的逻辑。

答案 1 :(得分:1)

您不必担心方法会有额外的增量,因为您的方法只接受单个参数。但是你确实需要防范其他黑客攻击:

让我们首先扩展Match对象,以便我们检查_id是否只是:

Match._id = Match.Where(function(id){
  check(id, String); // first make sure we're dealing with a string
  // then grep for an exactly 17 character alphanumeric string
  return /^[a-zA-Z0-9]{17,17}/.test(id); 
});

more on this technique

现在让我们采取你的第一种方法:

Meteor.methods({
  'argumentVoteYes':function(currentArgumentId){
    check(currentArgumentId,Match._id); // will error if not an _id

    var post = Arguments.findOne({ _id: currentArgumentId });
    var userId = Meteor.userId(); // the current user

    if ( post && userId ){ // make sure a real user is operating on an actual document
      // only update if no votes have been recorded OR
      // user hasn't already voted

      if ( !post.votedUp || post.votedUp.indexOf(userId) === -1 ){ 
        Arguments.update(currentArgumentId, {
          $pull: { votedDown: userId },
          $inc: { score: 2 },
          $addToSet: {votedUp: userId }
        });
      }
    }
  },

答案 2 :(得分:0)

之前我曾经想过同样的事情,我发现解决方案只是使用了一组userId,你不会从客户端传递(你只需保存当前用户的ID)并计算数组中的总ID。它没有两次添加相同的ID。

从我的代码中(您可以执行其余的检查,例如,如果用户处于不喜欢的数组中,请执行某些操作等)。

likeActivity: function (activityId) {
    Activities.update(activityId,{
        $addToSet: {
            likers: this.userId,
        }
    });
},

unlikeActivity: function (activityId) {
    Activities.update(activityId,{
        $pull: {
            likers: this.userId,
        }
    })
}

在我的帮手中:

likeCount: function() {
    return this.likers.length
}