防止用户多次点击“喜欢”的最佳方法

4
我正在为一个站点实现“喜欢”功能。用户无需登录,可以喜欢或不喜欢特定页面。最终我想能够列出获得最多赞的文章或故事清单。
我有一个非常简单的方法,目前使用onclick JavaScript函数通过ajax和php函数更新数据库。这个方法现在工作得很好。我想要做的是防止用户滥用按钮。
起初我考虑获取IP地址并将其存储在数据库中进行检查。是否有更好的方法?

3
没有用户登录,没有100%的绝对方法来做到这一点。在您的数据库中记录IP地址可以防止子网上的多个人喜欢您的内容。 - MonkeyZeus
不登录?我建议使用cookie,但所有方法都会有问题。 - mccainz
Cookie 可以帮助完成此任务。当用户点击“喜欢”一次时,请存储一个 Cookie。在处理“喜欢”点击时,请检查此 Cookie。 - user784540
谢谢帮助,如果可能的话,有人能详细解释一下关于cookie的想法吗? - null
1
嗨Steve,我也喜欢为未登录用户提供此功能,但我仍然记录用户记录,就像你说的那样。只记录IP地址,而不让他们知道自己被记录了(当然,在使用条款中说明是合乎道德的)。虽然其他实现方法(如cookie)存在易受攻击的缺陷,但这种方法也有两个缺点:1)用户可以轻松更改其IP地址;2)来自同一网络的两个人被视为一个用户。所以你决定,但在我看来,尽量依赖服务器上的数据,而不是用户计算机上的数据。 - jeff
显示剩余2条评论
4个回答

6

从技术角度来说,并没有绝对安全的方法。您可以通过允许每个IP用户代理组合投票来实现接近安全的效果。您需要在服务器端实现此功能。

PHP示例:

 $concienceKey = md5($_SERVER['REMOTE_ADDR'] . $_SERVER['USER_AGENT']);

 $query = "SELECT COUNT(*) FROM clickConcience WHERE key = `" . $concienceKey . "`";

 //run your query
 //.....and get the $count;
 //

 //already voted!
 if($count > 0){
      echo 'already voted';
      return false;
 }

 //remember entry
 $insert = "INSERT INTO clickConcience (key, datetime) VALUES (`" . $concienceKey . "`, NOW())";

 //run your query
 //.....and insert
 //

 return true;

1
$concienceKey非常适合我们在德国的数据保护法中使用。无需将IP保存在数据库中,而是使用md5哈希密钥。太完美了! - Martin
很高兴它能帮助到你,马丁! - Bas Kuis

5
简单明了的回答是,你无法做到。
如果我真的想垃圾邮件攻击你的“喜欢”按钮,我会找到方法来做到这一点,特别是如果你没有强制要求我登录(我曾经写过相当不错的机器人,并且在大型链接提交站点上进行过高效的垃圾邮件攻击)。
JavaScript只能阻止普通的垃圾邮件发送者或袜子垃圾邮件账户持有者。作为一个垃圾邮件发送者,我可以很容易地规避你的JavaScript,要么通过编程一个基于时间的机器人来喜欢你的帖子,要么直接向你的服务器发送请求(我甚至不会加载你的网站)。
如果你真的想有效地防止垃圾邮件发送者垃圾邮件这个功能(效率是关键词,因为垃圾邮件发送者仍然可以垃圾邮件攻击你的功能,但他们的赞不会计数),那么你需要记录每个IP地址喜欢帖子的地理信息(它不总是100%准确,但这是一个好的开始),然后在后台运行一个进程,检查可疑的起源并惩罚这样的赞(通过分配较少的价值或从总计中减去它们)。
例如,如果你的主要受众是居住在美国的人,但是一个帖子从墨西哥、萨尔瓦多、印度、澳大利亚、俄罗斯获得了很多赞,那么很有可能背后有一个使用代理或类似TOR的网络的垃圾邮件发送者,他/她可以随意更改他/她的IP地址。
记录几百万条记录后,你将有一个良好的基础来开始黑名单IP地址。我通常使用R编程语言来获取关于我的数据库的统计信息。
但是,一个好的垃圾邮件发送者可能会使用来自你受众国家或地理位置的受损计算机的IP地址列表,并使用这些IP地址滥用该功能。这些机器人更难发现,但你可以分析以前的帖子并得出有用的指标,如“喜欢/评论比”。
如果一个帖子有大量的赞,但评论数量很少,那么很可能有人垃圾邮件攻击了它,但再次,我可以编程我的机器人来喜欢并发布评论,使数字看起来自然。
我不确定你正在做什么样的项目,但如果它类似于链接提交,请勿根据喜欢的数量排名(无论你的用户喜欢什么)。喜欢的数量只应该是一个因素,你可以看看HackerNews或Reddit如何排列帖子(这些项目是开源的),但它是多种因素的组合。

那是一个相当全面的答案。如果这个网站真的达到了那样的地位,我会对自己感到非常印象深刻 :) - null

2

在首次点击后,只需隐藏该按钮即可。

如果使用AJAX处理程序发送单击,则更为合理...


1
使用Cookie。假设您有一个按钮,用户可以喜欢文章123456789。
<button id="like" articleID="123456789">Like</button>

script :

function setLike(articleID) {
    document.cookie=articleID+'=y';
}

function hasLiked(articleID) {
    var cookies=document.cookie.split(';');
    for (var i=0;i<cookies.length;i++) {
        var cookie=cookies[i].split('=');
        if (cookie[0]==articleID) return true;
    }
    return false;
}

var button=document.getElementById('like');

button.onclick=function() {
    var articleID=this.getAttribute('articleID');
    if (!hasLiked(articleID)) {
        //register the like in your system
        //...
        //
        setLike(articleID);
    } else {
        alert('You cant like or dislike an article twice');
    }
}

当然,用户可以删除所有的cookie - 但是用户也可以从100台不同的计算机上喜欢同一页面/文章。以上措施可以防止最常见的情况:人们在短时间内反复从同一台计算机上点击“喜欢”或“不喜欢”很多次。

谢谢,我真的应该更多地了解一下cookie,它们仍然让人望而生畏 :( - null
完全不是这样,但你看到的所有脚本都使它变得如此困难和复杂,过度了。它只是一个字符串,你可以分割或解析它。 - davidkonrad
我正在尝试将其与我已经放置的ajax调用结合起来。您能否告诉我可能出了什么问题? - null
没有产生任何影响。我不确定问题出在哪里,但我认为 hasLiked 没有被设置,否则就不应该发起ajax调用。 - null
你能不能建立一个JSFiddle?我讨厌Pastebin,它让我做噩梦。还有删除一些评论,我会删除我的。SO不喜欢过多的辩论。 - davidkonrad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接