答案是:php 8.1 验证码长度校验必须用 mb_strlen($clean, 'utf-8') 配合预清洗(清除零宽字符/bom)和严格正则校验,确保准确、安全、防绕过。

PHP 8.1 判断字符串长度用于验证码,核心是**准确、安全、防绕过**——验证码本质是短字符串(通常 4–6 位纯字母数字),但必须杜绝因编码、类型、空值或边界情况导致的误判。
用 mb_strlen() 显式指定 UTF-8,哪怕只是 ASCII
验证码输入理论上不含中文或 emoji,但用户可能误粘贴空格、零宽字符甚至 BOM 头。mb_strlen() 比 strlen() 更健壮:
- 它能正确处理 UTF-8 编码下的所有合法字符,包括不可见控制符(配合后续清洗)
- PHP 8.1 中 strlen(null) 会抛 TypeError,而 mb_strlen(null, 'UTF-8') 返回 0 —— 更利于统一兜底
- 即使输入全是 a-z0-9,显式写
mb_strlen($code, 'UTF-8')也比strlen($code)更一致、更可维护
先清洗,再测长:trim() 不够,要清零宽和控制字符
用户从微信、QQ 或某些编辑器复制的验证码,常带零宽空格(\xe2\x80\x8b)、BOM(\xef\xbb\xbf)或制表符。仅用 trim() 无法清除:
- 推荐预处理:
$clean = trim(preg_replace('/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f\x{200b}-\x{200f}\x{feff}]/u', '', $input)) - 之后再判断:
if (mb_strlen($clean, 'UTF-8') !== 4) { /* 长度不符 */ } - 这步不能省——否则攻击者可用零宽字符“撑长”4 位验证码,绕过长度校验
必须校验类型 + 非空 + 仅含预期字符
长度只是第一关。验证码还需确保是「干净的字符串」且「只含允许字符」:
- 用
is_string($input)排除非字符串(如数组、null、true) - 用
!empty($clean)或mb_strlen($clean, 'UTF-8') > 0确保非空 - 用正则严格限定字符集:
if (!preg_match('/^[A-Za-z0-9]{4}$/', $clean)) { /* 格式非法 */ } - 注意:
^...$是必须的,防止前后混入非法字符
不依赖前端,不拼接正则,不假设编码
验证码校验必须 100% 在后端完成:
- 前端 JS 的
.length或Array.from().length可被禁用或绕过,仅作体验优化 - 绝对不要用
preg_match("/^.{{$len}}$/", $s)动态拼正则——这是反模式,有注入与性能风险 - 不依赖
mb_internal_encoding(),始终显式传'UTF-8';若不确定输入来源,可加mb_check_encoding($clean, 'UTF-8')双保险
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











