PHP聊天室访客登录输入阿拉伯语昵称报无效输入问题排查
问题根因
该报错由3处代码逻辑缺陷共同导致:
- 错误映射错位:接口初始化时直接将错误字段标记为
nickname,但全流程校验逻辑从未对昵称字段做非空、合法性校验,所有校验逻辑都针对username字段,只要用户名校验不通过就直接抛出昵称无效的错误提示,和实际出问题的字段完全不匹配。 - 字符清洗函数不兼容阿拉伯语这类UTF-8多字节字符:
sanitize_username内所有preg_replace正则规则都未添加u(UTF-8模式)修饰符,PCRE默认以单字节编码匹配字符,阿拉伯语的双字节序列会被识别为非法字符,经过正则替换后直接变为空字符串,触发「字段为空」的报错。
之所以注册流程正常,是因为注册流程要求用户显式填写用户名,且注册逻辑调用字符清洗前会做UTF-8编码预处理;而访客场景下没有单独的用户名输入框,前端会自动把昵称框的内容填充为username参数提交,阿拉伯语被清洗为空后直接触发校验失败。 - 后端逻辑过度依赖前端传参:访客模式本身不需要用户单独设置用户名,但后端没有做兜底逻辑,只要前端没传
username参数就直接判定为输入非法,当前端自动填充逻辑对非拉丁字符兼容不佳时,会直接触发报错。
修复方案
按以下顺序修改代码即可解决问题:
- 补全访客逻辑的参数兜底:在用户名校验逻辑前增加判断,若未接收到
username参数,直接取用户提交的nickname作为初始用户名,不要直接判定为校验失败,同时补全nickname字段的非空校验,错误提示与实际异常字段对应。 - 修复字符清洗函数的UTF-8兼容性:给
sanitize_username内所有正则规则加上u修饰符,修改后代码如下:
function sanitize_username($username, $strict = false) { $username = strip_all_tags($username); $username = remove_accents($username); $username = preg_replace('|%([a-fA-F0-9][a-fA-F0-9])|u', '', $username); $username = preg_replace('/&.+?;/u', '', $username); if ($strict) { $username = preg_replace('|[^a-z0-9 _.\-]|iu', '', $username); } $username = str_replace(array('\'', '"', ',', '@', ';', '(', ')', '[', ']', '<', '>', '{', '}', '?', '&'), '', $username); $username = trim($username); $username = preg_replace('|\s+|u', ' ', $username); $username = preg_replace('/\s+/u', '-', $username); return $username; }
- 修复
sanitize_slug的参数传递bug:当前函数调用sanitize_username时硬编码传入$strict = false,会忽略外部传入的strict模式配置,修改为:
function sanitize_slug($slug, $strict = false) { return sanitize_username($slug, $strict); }
内容的提问来源于stack exchange,提问作者M.Alkenani
相关产品推荐
相关产品推荐

