【问题标题】:How to prevent user from posting multiple times?如何防止用户多次发帖?
【发布时间】:2017-02-05 11:00:26
【问题描述】:

我有一个应用程序,用户只能每五分钟发一次帖子。

我正在尝试找出最安全的方法来防止用户在这五分钟内多次发帖。

我想出的第一个解决方案是检查用户发帖时更新的 lastPostTimestamp 值。

我发现的潜在问题是,如果某人的互联网速度非常慢或滞后,则用户可能会在 Firebase 上更新时间戳之前向该按钮发送两次垃圾邮件并获得两个帖子。

然后的路线是创建局部变量和设置为 5 分钟的计时器,并检查 firebase 和局部变量,但是检查本地变量(如果存在)和 firebase(如果存在)似乎都很混乱和奇怪。

如果用户切换设备,我不能使用 UserDefaults。

关于如何顺利检查以确保用户在过去 5 分钟内没有向 Firebase 发送信息的任何想法?

【问题讨论】:

    标签: ios swift firebase firebase-realtime-database


    【解决方案1】:

    处理此问题的一种方法是在按钮第一次激活后禁用它,并且在用户可以再次发布之前不要重新激活它。

    【讨论】:

      【解决方案2】:

      我会结合使用时间戳检查(服务器端)和单击时禁用按钮(本地)。

      可以通过再次启动应用重新激活按钮,但确实可以防止向按钮发送垃圾邮件(您的连接速度慢的问题)。

      时间戳可防止重新打开应用并再次发布。

      【讨论】:

        【解决方案3】:

        我认为最安全的方法是防止与您的类似的时间问题,检查服务器端。如果您在客户端检查它并且如果您没有在服务器端检查它,则意味着您的应用程序存在漏洞。因为用户可以更改手机的当地时间。所以他/她可以操纵你的服务。因此,我建议您应该始终检查服务器端的时间操作对您的应用程序更安全。

        【讨论】:

          【解决方案4】:

          听起来您可以使用 transactions 来阻止竞争条件漏洞利用并使用 DB 级安全规则 来强制执行时间限制。但是,它不适用于 .push() 和自动 ID(不知道您是否使用它们,如果使用,您可能需要重写您的客户端以开始使用顺序帖子 ID)。

          使用事务块避免 Firebase 中的竞争条件

          您的客户端应用会根据最后一个已知的帖子 ID 依次生成新帖子的路径。然后在事务块中,您将检查该路径上的帖子是否已经存在,如果存在则中止。

          伪代码以后可能会用 Swift/iOS SDK 重写,但你明白了

          let post = new Post("/path/to/posts/\(lastPostId + 1)")
          
          post.transaction(function (currentPostData) {
            if (currentPostData !== null) { return }
            ...
          })
          

          如果用户快速提交两次,在一种情况下事务处理程序将不得不返回任何内容并失败。

          另见

          使用数据库安全规则实施时间限制

          您可以在提交新帖子的同时提交上一篇博文 ID,然后使用 Firebase 实时数据库规则检查上一篇博文的时间戳是否足够旧。

          {
            "rules": {
              "posts": {
                "$post_id": {
                  ".write": "(now - 300000) > root.child('posts').child(data.lastPostId).child('timestamp').val()"
                }
              }
            }
          }
          

          如果您可以在规则字符串本身中获取最后一篇文章的时间戳会更好,但我现在看不到这样做的方法。

          如果您也可以使用规则来避免竞争条件漏洞,那就更好了,但似乎规则语言太有限,也不允许这样做。

          另见

          【讨论】:

            【解决方案5】:

            因为你有最后一篇文章的 lastPostTimestamp 值。我会说为用户的最后一篇帖子设置一个观察者,然后:

                    let time = lastPostTimestamp
                    let datum = Date(timeIntervalSince1970: time as! TimeInterval)
                    let seconds = Date().timeIntervalSince(datum as Date)
            
                    guard seconds > 300 else {return} // 5 minutes
            
                    button.isEnabled = true
            

            【讨论】:

              【解决方案6】:

              在我看来,这应该在服务器端处理。

              帖子的唯一ID很简单。

              当用户发帖时:

              1. 检查是否已经发布?
              2. 如果是,则更新它
              3. 否则,将其插入为新的。

              【讨论】:

              • 重点是时间段的5分钟,根据您的建议用户可以每分钟发布不同的帖子,这是不可接受的...
              猜你喜欢
              • 1970-01-01
              • 2011-11-23
              • 1970-01-01
              • 2017-07-05
              • 1970-01-01
              • 2022-07-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多