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

ThinkPHP 雙重轉義問題根因分析與三種徹底解決方案

     編輯:PHP 相關知識

ThinkPHP 雙重轉義問題根因分析與三種徹底解決方案

ThinkPHP 早期版本(2.x/3.x)在 magic_quotes_gpc = On 環境下,極易出現資料庫寫入雙重反斜線(\\'、\\")的問題。根因在於框架未判斷 PHP 內建轉義即自行再次 addslashes,導致「PHP 自動轉義 + 框架手動轉義」雙重處理。本文深入剖析機制,提供三種徹底解決方案,並說明為何某些常見修法不可取。

一、問題重現與根因

現象: 表單提交「O'Reilly」入庫變成「O\\'Reilly」,前台顯示帶反斜線。
環境: PHP 5.3 以下且 php.ini 設定 magic_quotes_gpc = On(PHP 5.4+ 已移除此特性)。
流程:

  1. PHP 自動對 $_GET/POST/COOKIE 執行 addslashes(單引號變 \')。
  2. ThinkPHP 入口檔或 Model escape_string() 再次執行 addslashes / mysql_real_escape_string。
  3. 結果:\' → \\',資料庫存入雙重反斜線。

二、方案一:入口檔統一「去除再統一加回」(推薦,相容性最佳)

在 index.php 最早期(引入框架前)插入:

<?php
if (get_magic_quotes_gpc()) {
    function stripslashes_deep($val) {
        return is_array($val) ? array_map('stripslashes_deep', $val) : stripslashes($val);
    }
    $_GET    = array_map('stripslashes_deep', $_GET);
    $_POST   = array_map('stripslashes_deep', $_POST);
    $_COOKIE = array_map('stripslashes_deep', $_COOKIE);
    $_REQUEST= array_map('stripslashes_deep', $_REQUEST);
}
// 之後框架內部再按需 escape,邏輯統一
?>

優點: 徹底還原原始資料,框架後續統一處理,不侵入核心類,升級無痛。
注意: 必須在 define('APP_PATH') 之前、任何框架代碼執行前。

三、方案二:修改 Db 驅動 escape_string() 為「先去再加」(次推薦)

編輯 ThinkPHP/Lib/Think/Db/Driver/Mysql.class.php(或對應驅動):

public function escape_string($str) {
    // 關鍵:無論來源,先移除現有反斜線,再按資料庫規則轉義
    $str = stripslashes($str);
    if ($this->_linkID) {
        return mysql_real_escape_string($str, $this->_linkID);
    }
    return mysql_escape_string($str); // 舊版 fallback
}

優點: 集中在資料庫層解決,不影響其他元件。
缺點: 修改核心檔,升級覆蓋;若專案使用 PDO/mysqli 驅動需同步修改對應類。

四、方案三:關閉 magic_quotes_gpc(根治,需伺服器權限)

修改 php.ini:

magic_quotes_gpc = Off
magic_quotes_runtime = Off
magic_quotes_sybase = Off

或在 .htaccess / .user.ini:

php_flag magic_quotes_gpc Off

優點: 移除 PHP 層面干擾,框架邏輯單純化。
缺點: 共享主機可能無權限;舊專案若依賴 magic_quotes 可能產生注入風險(需全站檢查)。

五、為何「只在 magic_quotes_on 時跳過 escape」不可取?

常見錯誤寫法:

// 錯誤示範
public function escape_string($str) {
    if (get_magic_quotes_gpc()) return $str; // 危險!
    return mysql_real_escape_string($str);
}

反例: 若資料來源為 file_get_contents()、資料庫讀取、API 回傳等非 GPC 來源,magic_quotes_gpc 不會處理,導致這些資料「漏逃脫」,造成 SQL 注入隱患。
正確原則: 統一輸入 → 統一清洗 → 統一轉義,勿依賴來源判斷。

六、現代版本(ThinkPHP 5/6、Laravel)的處理

  • PHP 5.4+ 已移除 magic_quotes_gpc,問題自然消失。
  • 新版框架採用 PDO 預處理語句(Parameter Binding),完全繞過手動轉義,從根本杜絕注入與雙重轉義。
  • 若維護舊專案無法升級,請採用方案一或二,並規劃遷移至預處理架構。

總結: 雙重轉義本質是「多層轉義邏輯疊加」。最穩健做法是入口統一 stripslashes,框架統一 escape/預處理。若擁有伺服器控制權,關閉 magic_quotes_gpc 為一勞永逸之計。

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