node.js - Socket.IO 套接字保护,无需身份验证

标签 node.js sockets socket.io

我使用 Express.js 和 socket.io (可用 here )创建了一个简单的 Node.js 应用程序,用户单击按钮,页面上的数字就会递增。在连接到该页面的所有客户端中,该数字也会实时递增。我正在使用 Web 套接字和 socket.io 来获取客户端-服务器通信和实时号码更新系统。

我正在使用flood-protection模块将套接字限制为每秒 5 次,但这确实不会使游戏变得非常有趣,因为每秒的点击量很少,而且黑客只需使用 setInterval 即可自动取得相当大的进展,即使是在如此低的速率下。

我的问题:

  1. 我不希望用户必须验证自己的身份 - 任何人都应该能够玩!

  2. 如果可能的话,我希望将点击率保持在每秒 15 次点击左右。

  3. 我不希望人们能够发送套接字消息并自动单击浏览器控制台中的按钮。

Here's the program :

index.js

var express = require("express");
var http = require("http");
var socketIO = require("socket.io");
var path = require("path");
var fs = require("fs");
var FloodProtection = require("flood-protection").default;
__dirname = path.resolve();

function btoa(str) {
  return new Buffer(str, 'latin1').toString('base64');
};

function atob(b64Encoded) {
  return new Buffer(b64Encoded, 'base64').toString('latin1');
};

var app = express();
app.get("/", function(req, res){
  res.sendFile(__dirname + "/index.html");
});

var temp;
num = temp | parseInt(atob(fs.readFileSync("num.txt"))) | 0

var server = http.createServer(app);
var io = socketIO.listen(server, {log: true});
io.sockets.on("connection", (socket) => {
  protector = new FloodProtection({rate: 5, per: 1})
  io.sockets.emit("update", num);
  socket.on("push", (value) => {
    if (protector.check()) {
      num++;
      temp = num
      io.sockets.emit("update", temp);
    } else {
      io.sockets.emit("update", "You can only click the button five times per second.")
      socket.disconnect(2)
      setTimeout(()=>{}, 3000)
    }
  });
  socket.on("disconnect", () => {
    fs.writeFile("num.txt", btoa(String(temp)), (err) => {
      if (err) throw err;
      console.log("saved | new num: " + temp);
    })
  })
});

server.listen(5000);

index.html

<html>
  <head>
    <title>A Button</title>
  </head>
  <body>
    <button onclick='push();'>Click me!</button>
    <p id="out"></p>
  </body>
  <script type="text/javascript" src="/socket.io/socket.io.js"></script>
  <script type="text/javascript">
    var variableFromFrontEnd = 2;
    var socket = io.connect("/");
    socket.on("connect", function() {
      socket.on("update", function(val) {
        document.getElementById("out").innerHTML = val
      });
    });
    socket.on("disconnect", function() {
      setTimeout(()=>{socket.connect();}, 1000);
    });
    function push() {
      if (socket.connected) {
        socket.emit("push");
      }
    }
  </script>
</html>

num.txt 是一个 base-64 编码的数字。

那么,有没有一种方法可以在没有显着的速率限制或身份验证的情况下做到这一点?或者我只是必须使用速率限制?

最佳答案

用户作弊的方式有很多种,防止作弊的方法也有很多。一般规则是你只能“让事情变得更难”(如果你幸运的话,足够难,以至于潜在的作弊者在成功之前就失去了兴趣)。

对于基于浏览器的游戏,我会确保您至少确保您的游戏完全缩小/简洁(因此您的 JavaScript 代码尽可能不可读,并且直接调用“单击”函数更困难),并在消息中构建校验和(因此用户不能直接向服务器进行套接字调用)。

完成此操作后,您仍然需要处理直接使用代码或插件在元素上生成点击事件的用户,或者使用浏览器外部的程序在按钮上方重复生成点击事件的用户。对此最好的防御不是阻止它,而是检测它 - 可能在服务器端,通过观察具有人类不可能的持续点击率的用户,然后炸毁他们的游戏/暂时禁止他们的IP等。

查看相关问题Ways to prevent or reduce cheating了解更多相关想法(这个问题是关于一般的客户端服务器游戏,而不是浏览器游戏,但其中一些讨论仍然有用)。

关于node.js - Socket.IO 套接字保护,无需身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53990781/

相关文章:

node.js - socket.io 加入房间的问题

jquery - 在 Jade 和 Bootstrap 中使用 Dropdowns 给我 $ (".dropdown-toggle")。dropdown 不是函数

node.js - 使用 typescript 时nodemon不刷新

c - 如果客户端无法应对(buffer++),如何停止写入套接字(AF_LOCAL/UNIX、SOCK_STREAM)?

javascript - 使用 socket.io 和 Express JS 的聊天应用程序

javascript - 通过 socket.io 添加 ssl 后无法发出消息

node.js - 将 TypeScript 枚举与 Mongoose 模式一起使用

node.js - Node.js REPL 的问题

java - BufferedReader.ready() 行为的差异

javascript - 使用 node.js 和 socket.io 每秒广播