2017-04-24 73 views
0

下面是一些代码(具有相关联的数据),用于计数东西流星应用的本质。计数可以连接在一起,这样一是可以增加另:流星 - 检测无限循环

// The counting and linking code. 
Meteor.methods({ 
    'counts.increment'(countId) { 
     const count = Counts.findOne(countId); 
     Counts.update(countId,{ $inc: { count: 1 } }) 
     Meteor.call('counts.check-links',count._id); 
    }, 
    'counts.check-links'(countId){ 
     var count = Counts.findOne(countId); 
     count.links.forEach(function (linkId) { 
      updated = false; 
      const link = Links.findOne(linkId); 
      const primary = Counts.findOne(link.primary); 
      const secondary = Counts.findOne(link.secondary); 
      if (primary.count == link.level) { 
       updated = true; 
       Counts.update(secondary._id, {$inc: {count: 1}}); 
      } 
      if (updated) { 
       Meteor.call('counts.check-links',secondary._id); 
      } 
     }) 
    } 
}) 

// Some data... 
Count: { 
    _id: 1, 
    value: 0, 
    name: A, 
    links: [3] 
} 

Count: { 
    _id: 2, 
    value: 0, 
    name: B, 
    links: [4] 
} 

Link: { 
    _id: 3, 
    primary: 1, 
    secondary: 2 
} 

Link: { 
    _id: 4, 
    primary: 2, 
    secondary: 1 
} 

所以,每个计数链接到其他如果Meteor.call('projects.increment',1)称为该代码会崩溃。检测这样的设置可以是相当困难的,因为有可能是计数的非常复杂的安排和链接也可以减少,置零,操作每隔N计数&℃。 & c。不过,为了提出这个问题并不重要。我认为

一种可能性是添加内counts.check-links一个计数器,该计数器将环路的任意数量后停止执行,例如5.假定为防止篡改,这个计数器的值必须存储在数据库中并通过Meteor方法执行。它将需要在任何check-links调用序列结束时重置。

我不知道这是否是最好的办法,或者如果这样怎么可能是一个很好的方式来实现它,所以我很想知道,如果任何人有任何建议。

+1

确保验证您的服务器方法或其超级假冒此方法调用或做一些nosql注入。 – Dude

+0

服务器只将数据发布属于已登录的用户,并且该方法调用也检查正在对数据执行的操作的登录用户拥有,因此应该有希望覆盖它。 – knirirr

+0

我应该补充说,在实际的应用程序中还有一个Meteor.method参数的检查 - 我从这里的例子中省略了这种事情。 – knirirr

回答

1

您可以创建一组已访问过的所有对象(“计数”)的;所以如果你按照这样一个对象的链接,你可以避免再次处理它,从而进入无限递归。

编辑:例子 我对流星不熟悉,所以请原谅它是否不能像预期的那样工作......这是所有允许指向对象引用的编程语言的常见问题,该解决方案遵循类似的模式。

// The counting and linking code. 
Meteor.methods({ 
    ... 
'counts.check-links'(countId, alreadyVisited){ 

    if (!alreadyVisited) alreadyVisited = {}; 
    if (alreadyVisited[countId]) return; 
    alreadyVisited[countId] = true; 

    var count = Counts.findOne(countId); 
    count.links.forEach(function (linkId) { 
     updated = false; 
     const link = Links.findOne(linkId); 
     const primary = Counts.findOne(link.primary); 
     const secondary = Counts.findOne(link.secondary); 
     if (primary.count == link.level) { 
      updated = true; 
      Counts.update(secondary._id, {$inc: {count: 1}}); 
     } 
     if (updated) { 
      Meteor.call('counts.check-links',secondary._id, alreadyVisited); 
     } 
    }) 
} 
+0

谢谢,我会放弃。大概一个人应该清空已经在最后的else块中,因为如果没有更新,那么就没有必要检查更多的链接。 – knirirr

+0

看起来像这样做。为了安全起见,我没有在方法中创建已存在的方法,而是将其存储在数据库中,以便我可以应用一些检查(例如登录用户)。否则,我已经使用了你放在那里的东西。 – knirirr