Workerman 5.2.3 中协议层仅负责分包解包,数据校验须在 onMessage 中完成;协议层可在 input/decode 做轻量预检,业务层用 illuminate/validation 或手写函数做完整校验,并结合连接状态(如 is_authed)和日志辅助定位问题。

在 Workerman 5.2.3 中,自定义协议本身不负责业务层数据校验,它的职责是可靠地完成分包、解包和打包。数据校验必须放在业务逻辑中(比如 onMessage 回调里),但可以结合协议设计提前过滤明显非法数据,避免无效解析。
协议层做基础预检(input/decode 中拦截明显异常)
虽然 Workerman 协议类不替代业务验证,但在 input 和 decode 里加轻量级检查能提升健壮性:
-
在
input中拒绝超长或格式错乱的缓冲区:比如限制单包最大长度为 1MB,防止恶意堆积;若检测到非法换行符位置(如开头就是\n)、或连续多个\n,可直接返回false让连接断开 -
在
decode中做语法级校验:例如 JSON 协议下,json_decode($buffer, true)返回null且json_last_error() !== JSON_ERROR_NONE,说明不是合法 JSON,此时可返回null或抛异常(注意:Workerman 会把null当作无效数据,onMessage不会被调用)
业务层做完整数据验证(推荐主战场)
真正有意义的校验——字段存在性、类型、范围、业务规则——必须在 onMessage 中进行。Workerman 本身无内置验证器,需引入第三方库或手写规则:
-
使用 illuminate/validation(Laravel 验证组件):通过 Composer 安装
illuminate/validation和illuminate/translation,在onMessage中创建Validator实例,传入$data和规则数组(如['type' => 'required|string|in:message,login', 'content' => 'required_if:type,message|min:1']) -
手写轻量校验函数:对简单场景,可封装一个
validateRequired($data, ['type', 'content'])或validateType($data['type'], ['message', 'ping']),快速失败并记录错误日志 -
统一错误响应:校验失败时,不要直接
return,而是调用$connection->send(['code' => 400, 'msg' => '参数缺失']),保持通信契约清晰
结合 Token 或上下文做关联校验
有些校验依赖连接状态,比如“登录后才能发消息”。这时不能只看当前包,还要查连接绑定的用户信息:
- 在
onConnect或首次认证成功时,给$connection添加属性,如$connection->uid = 123、$connection->is_authed = true - 在
onMessage中先检查$connection->is_authed,再校验业务字段。未认证连接发来的消息,直接拒绝,不进入后续验证流程
日志与可观测性辅助定位问题
校验失败时,仅返回错误码不够。建议记录结构化日志,包含:connection_id、client_ip、原始 $buffer(脱敏后)、校验失败的具体字段和原因。这能快速区分是客户端 bug 还是协议误配。

















