首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

addslashes / stripslashes 與 Magic Quotes 的愛恨情仇

     編輯:PHP 相關知識

現象還原

輸入 Tom's book's → 入庫前 addslashes() → 數據庫實際存儲 Tom's book's(無反斜杠) → 讀出直接 echo 顯示正常。但開發者困惑:為何不需要 stripslashes() 也能正常顯示?

核心真相:Magic Quotes GPC 自動轉義

PHP ≤ 5.3 預設開啟 magic_quotes_gpc = On,會在請求進入腳本前,**自動對 GET/POST/COOKIE 數據執行 addslashes()**。

流程如下:

  1. 用戶提交 Tom's book's
  2. PHP 內核自動轉義 → Tom\'s book\'s(在 $_POST 中)
  3. 代碼再次 addslashes($_POST['name']) → Tom\\'s book\\'s(雙重轉義)
  4. MySQL 入庫時解析轉義,實際存儲 Tom\'s book\'s
  5. 讀出時 MySQL 返回 Tom's book's(單反斜杠被解析為字面單引號)
  6. 直接 echo 顯示正常

**結論**:雙重轉義在 MySQL 入庫環節「剛好」抵消,但這是極不穩定的巧合。

正確處理姿勢

方案一:關閉 Magic Quotes(推薦,PHP 5.4+ 已移除)

; php.ini
magic_quotes_gpc = Off

然後統一使用 預處理語句(Prepared Statements),完全避開手動轉義:

$stmt = $mysqli->prepare("INSERT INTO t(name) VALUES (?)");
$stmt->bind_param('s', $_POST['name']);
$stmt->execute();

方案二:無法關閉 Magic Quotes 時的兼容寫法

function cleanInput(array $data): array {
    if (get_magic_quotes_gpc()) {
        $data = array_map('stripslashes', $data);
    }
    return $data;
}
$_POST = cleanInput($_POST);
$_GET  = cleanInput($_GET);
$_COOKIE = cleanInput($_COOKIE);
// 之後再用 mysqli_real_escape_string 或預處理

為何不推薦 mysql_real_escape_string?

  • 需建立數據庫連接後才能調用,耦合度高。
  • 字符集設置錯誤時(如連接未 SET NAMES utf8mb4)會導致注入繞過(GBK 雙字節漏洞)。
  • 預處理語句從协議層面分離數據與代碼,**原理上免疫注入**,性能更好(可複用執行計劃)。

歷史遺留項目快速修復清單

  1. 檢查 phpinfo() 中 magic_quotes_gpc 狀態。
  2. 入口文件統一清洗 $_GET/$_POST/$_COOKIE(如上 cleanInput)。
  3. 全局搜索替換 mysql_query / mysqli_query 拼接 SQL 為預處理語句。
  4. 輸出時按上下文編碼:HTML 用 htmlspecialchars,JS 用 json_encode,URL 用 rawurlencode。**永遠不要用 stripslashes 作為輸出處理**。

總結

addslashes/stripslashes 是上世紀的產物,配合 Magic Quotes 產生無數坑。現代 PHP(≥5.4)已移除 Magic Quotes,**預處理語句 + 上下文輸出編碼** 是唯一標準答案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved