bool mb_check_encoding ( string|null $string = null, string|null $encoding = null ): bool
$string:待檢查字節流,省略時檢查所有請求輸入($_GET、$_POST、$_COOKIE 等)。$encoding:目標編碼,默認 mb_internal_encoding()。true 表示通過驗證,false 表示存在無效字節序列。核心價值:有效防範「無效編碼攻擊」,攻擊者通過構造非法字節序列繞過安全檢查、導致邏輯漏洞或緩衝區溢出。
<?php
// 檢查單個字符串是否為合法 UTF-8
$str = "正常中文";
var_dump(mb_check_encoding($str, 'UTF-8')); // true
// 檢查包含非法字節的字符串
$bad = "正常\xC0\xAF中文"; // \xC0\xAF 為非法 UTF-8 序列
var_dump(mb_check_encoding($bad, 'UTF-8')); // false
// 批量檢查請求輸入(省略參數)
if (!mb_check_encoding(null, 'UTF-8')) {
die('請求包含非法編碼,疑似攻擊');
}
若環境無 mbstring 擴展,可參考以下純 PHP 實現(摘自原文並優化註釋):
<?php
function check_utf8($str)
{
$len = strlen($str);
for ($i = 0; $i < $len; $i++) {
$c = ord($str[$i]);
if ($c <= 127) {
continue; // ASCII 字符,單字節
}
// 多字節序列首字節判斷
if ($c > 247) return false; // 5-6 字節(UTF-8 實際只到 4 字節)
elseif ($c > 239) $bytes = 4; // 11110xxx
elseif ($c > 223) $bytes = 3; // 1110xxxx
elseif ($c > 191) $bytes = 2; // 110xxxxx
else return false; // 10xxxxxx 不能作為首字節
// 檢查剩餘長度
if (($i + $bytes) > $len) return false;
// 校驗後續字節:必須為 10xxxxxx (128-191)
while (--$bytes > 0) {
$i++;
$b = ord($str[$i]);
if ($b < 128 || $b > 191) return false;
}
}
return true;
}
<?php
// 簡易中間件示例
function validateEncodingMiddleware(callable $next)
{
if (!mb_check_encoding(null, 'UTF-8')) {
http_response_code(400);
exit('Invalid encoding detected');
}
return $next();
}
<?php
$content = file_get_contents($_FILES['upload']['tmp_name']);
if (!mb_check_encoding($content, 'UTF-8')) {
throw new RuntimeException('上傳文件包含非法 UTF-8 序列');
}
<?php
function safeInsert(PDO $pdo, string $table, array $data)
{
foreach ($data as $key => $val) {
if (is_string($val) && !mb_check_encoding($val, 'UTF-8')) {
throw new InvalidArgumentException("字段 $key 包含非法編碼");
}
}
// 執行插入...
}
| 編碼名稱 | PHP 常量/字符串 | 適用場景 |
|---|---|---|
| UTF-8 | 'UTF-8' | 現代 Web 應用默認編碼 |
| GBK/GB2312 | 'GBK' | 舊系統兼容、中文 Windows 環境 |
| ISO-8859-1 | 'ISO-8859-1' | 西歐語言、舊版 MySQL latin1 |
| Big5 | 'Big5' | 繁體中文舊系統 |
mb_check_encoding 能轉換編碼:它只驗證,不轉換。轉換請用 mb_convert_encoding() 或 iconv()。$_POST['field'] 不夠,攻擊者可藏在 Cookie、Header、文件名等處。建議入口統一調用 mb_check_encoding(null, 'UTF-8')。phpinfo() 中載入 mbstring 擴展,否則函數不存在。mb_check_encoding 是 PHP 內置的編碼安全閘門,代價極低(C 層實現)、覆蓋面廣。將其納入請求入口、文件處理、數據入庫等關鍵路徑,能以最小成本阻斷一類隱蔽且危險的編碼攻擊。配合 mb_internal_encoding('UTF-8') 統一內部編碼,構建乾淨可靠的字符處理環境。