我正在制作一个基于玩家能够邀请其他玩家参加派对的网页,以及其他一些内容。
我有你的基本发送/接收/更新聊天/用户在你的聚会。唯一的问题是,有什么能阻止某人坐在那里打开开发者控制台,然后点击
socket.emit('updateUsers', 'Weiner');
socket.emit('updateUsers', 'Idiot');
socket.emit('updateUsers', 'Bad word');
socket.emit('updateUsers', 'Other stupid malicious really long spam the chat name');
我怎样才能阻止他们这样做呢?
(Full JS Stack, Node.js)谢谢!
我也遇到过这个问题,这是我的解决方案,因为垃圾邮件发出去(恶意套接字使用).
var spamData = new Object();
var spamCheckFunctions = ["updateUsers","moreEmits"]; // anti-spam will check these socket emits
var antiSpam = 3000; // anti spam check per milliseconds
var antiSpamRemove = 3; // -spam points per antiSpam check
var maxSpam = 9; // Max spam points before disconnect is thrown to the socket
io.sockets.on('connection', function (socket) {
// Spam Check, this binds to all emits
var emit = socket.emit;
socket.emit = function() {
data = Array.prototype.slice.call(arguments);
if(spamCheckFunctions.contains(data[0])){
addSpam(socket);
};
emit.apply(socket, arguments);
};
var $emit = socket.$emit;
socket.$emit = function() {
data = Array.prototype.slice.call(arguments);
if(spamCheckFunctions.contains(data[0])){
addSpam(socket);
}
$emit.apply(socket, arguments);
};
});
function maxSpamCheck(socket){
if(spamData[socket.username].spamScore>=maxSpam && !socket.spamViolated){
socket.spamViolated = true;
socket.disconnect();
}
}
function checkSpam(){
for(user in spamData){
if(spamData[user].spamScore>=1) spamData[user].spamScore-=antiSpamRemove;
}
return;
}
setInterval(checkSpam,antiSpam);
function addSpam(socket){
if(socket.spamViolated) return;
spamData[socket.username].spamScore+=1;
maxSpamCheck(socket);
}
// Then add this where your user is authenticated
function authenticate(socket){
socket.username = username // here you define username
socket.spamViolated = false;
spamData[socket.username] = {
spamScore: 0
}
}
Array.prototype.contains = function(k) {
for(var p in this)
if(this[p] === k)
return true;
return false;
};
基本上绑定到所有的发送,检查发送名称是否包含在spamCheckFunctions
中,如果包含,如果用户超过垃圾邮件得分(maxSpam
),则添加一个垃圾邮件点;他将无法接通。antiSpam
定义的每毫秒将减去antiSpamRemove
定义的用户垃圾邮件得分
我相信有更干净的解决方案,但这个对我来说很好:)
确保验证/认证用户。
这是我如何认证他们(不使用nodejs作为web服务器,但有django):
io.configure(function(){
io.set('authorization', function(data, accept){
if(data.headers.cookie){
data.cookie = cookie_reader.parse(data.headers.cookie);
return accept(null, true);
}
return accept('error', false);
});
});
现在你可以访问socket.handshake.cookie['sessionid']
(在我的情况下,这与django一起工作)然后将socket.handshake.cookie['sessionid']
与您的会话存储在web服务器上的条目相匹配
这通常是个难题。你可以做两件事:
1)在客户端使用自调用函数,即(function(w) {
// define your sockets here
var socket = ...;
})(window);
显然它是在客户端,所以这不是真正安全的。但有这样一堵墙也不是坏事。
2)在服务器端跟踪发布的频率。例如,如果有人在一秒钟内发布了5次,那么你可以假设这是一个垃圾邮件,你可以阻止该套接字。如果结合身份验证和复杂的注册(因此人们在创建新帐户时会遇到问题),它特别有效。
使用md5/sha密钥,其行为类似于cookie。
为特定用户生成密钥并将其发送到客户端,并始终检查传入请求是否具有相同的密钥
这不是完全安全的,因为黑客总是可以在源代码或本地存储中找到你的密钥,但试图通过混淆你的代码来隐藏它
防止垃圾邮件的一种方法是实现用户身份验证和/或数据包速率限制。添加一个中间件功能,该功能跟踪socketId和通过该套接字发送的数据包数量。当它超过您的限制时,断开套接字。
你甚至可以添加一个额外的功能来跟踪该套接字的IP地址,如果一个IP地址由于垃圾邮件而经常断开连接,你可以禁止该IP。在您的连接事件中添加一个检查,哪些IP地址是允许的
使用rate-limiter-flexible包来限制每秒的事件数。按IP限制是最简单的,但如果可能的话,最好按userId限制。
const app = require('http').createServer();
const io = require('socket.io')(app);
const { RateLimiterMemory } = require('rate-limiter-flexible');
app.listen(3000);
const rateLimiter = new RateLimiterMemory(
{
points: 5, // 5 points
duration: 1, // per second
});
io.on('connection', (socket) => {
socket.on('bcast', async (data) => {
try {
await rateLimiter.consume(socket.handshake.address); // consume 1 point per event from IP
socket.emit('news', { 'data': data });
socket.broadcast.emit('news', { 'data': data });
} catch(rejRes) {
// no available points to consume
// emit error or warning message
socket.emit('blocked', { 'retry-ms': rejRes.msBeforeNext });
}
});
});
详情见官方文档