【问题标题】:Socket.io - Prevent server crash if "client" emit wrong dataSocket.io - 如果“客户端”发出错误数据,防止服务器崩溃
【发布时间】:2017-11-18 00:21:22
【问题描述】:

目前我正在使用 node.js 和 socket.io 做一个项目。

如果想知道是否有任何方法可以自动验证客户端发送到服务器的数据。我不想对要在正在进行的函数中使用的每个变量使用if (!...) return; 来验证数据。

例如,我在 server.js

上有以下代码
socket.on('haveData', function(data) {
    db.query('SELECT * FROM user WHERE userid = ? LIMIT 1', [data.userid], function(errData, results, fields) {
        if (!errData && results.length) {
            ...
        }
    });
});

但是现在,如果我在浏览器的控制台中输入socket.emit('haveData');,socket.io 服务器就会崩溃——当然,没有数据发出

TypeError: Cannot read property 'userid' of undefined

【问题讨论】:

  • 要么在发送之前检查客户端数据,要么检查服务器中接收到的数据。这里没有其他选择,但你肯定会有if (!...)

标签: javascript node.js validation sockets socket.io


【解决方案1】:

您可以使用 Joi https://github.com/hapijs/joi

Joi 允许您为输入数据定义架构并使用 Joi.validate 方法对其进行验证(例如:https://github.com/hapijs/joi#example)。

Socket.on('event',function(data,callback){}) 接受一个回调函数,可以用来将错误信息传回给客户端。

示例代码:

const Joi = require('joi');

socket.on('data',function(data,callback){

    const schema = Joi.object().keys({
        userid : Joi.string().trim().required()
    })

    Joi.validate(data, schema, function (err, value) {
        if(err){
            //Error will be sent back to the client who emitted the event
            callback(err)
        }else{
            //Do  your stuff 
        }
    })
})

【讨论】:

  • 谢谢,看起来很有趣。因此,使用 Joi,我可以定义发送到服务器的数据 can 包含“userid、message、token、...”,例如,在 shema 内部,我可以说 userid 必须始终是整数并且消息必须是最大长度为 50 个字符的字符串。如果发送数据中的要求不等于 shema,我可以将错误发送回客户端并且服务器不会“崩溃”?对吗?
  • 是的。 Joi 有一个非常好的 API 用于验证输入。你应该检查一下。
  • 您还需要确保回调是一个函数。您可以在 callback: Joi.function().required() 之类的架构中使用 Joi 来执行此操作,也可以通过 if(callback && typeof callback == 'function') 使用 js 来执行此操作
【解决方案2】:

服务器端代码必须验证从客户端发送的所有数据。您根本无法完全信任客户端,因为客户端可能被修改/黑客攻击,甚至流氓客户端也可能连接到您的服务器。

在这种特殊情况下,您需要解决这个特殊问题的只是这个if (data && data.userid) 来检查您发送的内容:

socket.on('haveData', function(data) {
    if (data && data.userid) {
        db.query('SELECT * FROM user WHERE userid = ? LIMIT 1', [data.userid], function(errData, results, fields) {
            if (!errData && results.length) {
                ...
            }

        });
     } else {
         // send some error back or just ignore the faulty request
     }
});

如果你真的要小心,你甚至可以使用:

if (data && data.userid && typeof data.userid === "string")

这确保data 存在,data.userid 存在且不是空字符串,并且data.userid 是字符串。

【讨论】:

    猜你喜欢
    • 2019-03-15
    • 2019-07-04
    • 1970-01-01
    • 2019-05-09
    • 2018-10-19
    • 2021-01-26
    • 2017-07-25
    • 2015-11-17
    • 1970-01-01
    相关资源
    最近更新 更多