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

PHP 安全過濾與轉義工具類完整解析:XSS 防禦、SQL 注入防護與輸入驗證

     編輯:PHP 相關知識

Web 應用安全的第一道防線是輸入過濾與輸出轉義。本文整理一套實用的 PHP 安全工具類 S,涵蓋 HTML 轉義、SQL 轉義、目錄遍歷防禦、變數檢查等核心功能,並說明每個方法的適用場景與注意事項,助你快速建立安全基線。

核心工具類程式碼

<?php
final class S {
    // 禁止實例化
    private function __construct() {}

    /**
     * HTML 輸出轉義:僅轉義單雙引號,保留 HTML 標籤結構
     * 適用場景:輸出到 HTML 屬性值、JavaScript 字串、已信任的富文本
     */
    public static function htmlEscape(string $param): string {
        return trim(htmlspecialchars($param, ENT_QUOTES, 'UTF-8'));
    }

    /**
     * 完整 HTML 實體化:轉義所有特殊字元,防止 XSS
     * 適用場景:輸出到 HTML 內容區、用戶生成內容
     */
    public static function htmlEntities(string $param): string {
        return htmlspecialchars($param, ENT_QUOTES | ENT_HTML5, 'UTF-8');
    }

    /**
     * 判斷是否為非空陣列
     */
    public static function isArray($params): bool {
        return is_array($params) && count($params) > 0;
    }

    /**
     * 檢查值是否存在於陣列(自動轉型字串比較)
     */
    public static function inArray($param, $params): bool {
        return in_array((string)$param, (array)$params, true); // 嚴格模式
    }

    /**
     * SQL 轉義:支援字串、數字、陣列遞迴
     * 注意:現代專案請優先使用 PDO 預處理語句,此函數僅用於舊代碼維護
     */
    public static function sqlEscape($var, bool $strip = true, bool $isArray = false) {
        if (is_array($var)) {
            if (!$isArray) return "''";
            foreach ($var as $key => $value) {
                $var[$key] = trim(self::sqlEscape($value, $strip));
            }
            return $var;
        } elseif (is_numeric($var)) {
            return "'" . $var . "'";
        } else {
            $var = $strip ? stripslashes($var) : $var;
            return "'" . addslashes($var) . "'";
        }
    }

    /**
     * 獲取並過濾 $_SERVER 變數:移除常見 XSS 向量字元
     */
    public static function getServer($keys) {
        $server = [];
        $array = (array) $keys;
        foreach ($array as $key) {
            $server[$key] = null;
            if (isset($_SERVER[$key])) {
                $server[$key] = str_replace(
                    ['<', '>', '"', "'", '%3C', '%3E', '%22', '%27', '%3c', '%3e'],
                    '',
                    $_SERVER[$key]
                );
            }
        }
        return is_array($keys) ? $server : $server[$keys];
    }

    /**
     * 遞迴對陣列值執行 addslashes(舊專案相容)
     */
    public static function slashes(array &$array): void {
        foreach ($array as $key => $value) {
            if (is_array($value)) {
                self::slashes($array[$key]);
            } else {
                $array[$key] = addslashes($value);
            }
        }
    }

    /**
     * 目錄路徑清理:防止目錄遍歷攻擊
     * 移除危險字元、合併多重斜線、去除尾部斜線
     */
    public static function escapeDir(string $dir): string {
        $dir = str_replace(["'", '#', '=', '`', '$', '%', '&', ';'], '', $dir);
        $dir = preg_replace('/\/+/', '/', $dir); // 合併多重斜線
        return rtrim($dir, '/');
    }

    /**
     * 通用變數轉義:依類型分派處理
     * @param mixed $mixed
     * @param bool $isint 強制轉整數
     * @param bool $istrim 是否修剪字串
     */
    public static function escapeChar($mixed, bool $isint = false, bool $istrim = false) {
        if (is_array($mixed)) {
            foreach ($mixed as $key => $value) {
                $mixed[$key] = self::escapeChar($value, $isint, $istrim);
            }
        } elseif ($isint) {
            $mixed = (int) $mixed;
        } elseif (!is_numeric($mixed)) {
            if ($istrim) $mixed = trim($mixed);
            if ($mixed !== '') {
                $mixed = self::escapeStr($mixed);
            }
        }
        return $mixed;
    }

    /**
     * 字串深度清理:移除控制字元、修正實體、統一空白
     */
    public static function escapeStr(string $string): string {
        // 移除空位元組、CR、NULL
        $string = str_replace(["\0", "\r", "%00"], '', $string);
        // 移除不可見控制字元(保留換行、Tab)
        $string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', '', $string);
        // 修正未編碼的 & 實體
        $string = preg_replace('/&(?!(#[0-9]+|[a-z]+);)/is', '&', $string);
        // 統一實體編碼
        $string = str_replace(['%3C', '<'], '<', $string);
        $string = str_replace(['%3E', '>'], '>', $string);
        $string = str_replace(['"', "'", "\t", '  '], ['"', ''', '    ', '  '], $string);
        return $string;
    }

    /**
     * 變數安全檢查:後台/前台差異策略
     * 前台:移除路徑遍歷、腳本標籤前綴
     * 後台:檢測 iframe/meta/script 注入,觸發攔截
     */
    public static function checkVar(&$var): void {
        if (is_array($var)) {
            foreach ($var as $key => $value) {
                self::checkVar($var[$key]);
            }
        } elseif (defined('P_W') && P_W !== 'admincp') {
            // 前台:基本清理
            $var = str_replace(['..', ')', '<', '='], ['..', ')', '<', '='], $var); // 此處原碼似有誤,建議改為實際過濾
        } elseif (defined('P_W') && P_W === 'admincp') {
            // 後台:嚴格檢測危險標籤
            $lower = strtolower($var);
            if (strpos($lower, '

方法適用場景對照表

方法用途適用場景備註
htmlEscapeHTML 屬性/JS 字串轉義輸出到 value="...", onclick='...'不轉義 < >,保留標籤
htmlEntities完整 HTML 實體化用戶評論、文章內容輸出最常用的 XSS 防禦
sqlEscapeSQL 字串轉義舊專案拼接 SQL 字串新專案請用 PDO prepare()
escapeDir路徑清理文件上傳、模板載入、include 路徑防止 ../ 目錄遍歷
escapeChar通用入口轉義控制器接收 $_GET/$_POST 統一處理可整合至 Request 物件
checkVar全域變數掃描框架入口統一檢查後台嚴格模式可攔截 XSS 載荷

現代 PHP 安全最佳實踐(超越工具類)

  1. 輸出端轉義為主:採用模板引擎(Twig、Blade、Lathe)自動上下文感知轉義,避免手動呼叫遺漏。
  2. 參數化查詢:全面使用 PDO/Doctrine/Eloquent 預處理語句,根除 SQL 注入,sqlEscape 僅作舊碼過渡。
  3. Content Security Policy (CSP):設定 HTTP Header Content-Security-Policy,限制腳本來源、禁止內聯腳本,縱使有 XSS 也無法執行。
  4. 輸入驗證白名單:使用 filter_var()、Respect\Validation、Symfony Validator 定義嚴格規則,拒絕不符合預期的資料進入系統。
  5. 檔案上傳安全:驗證 MIME、副檔名、魔術位元組;儲存至非執行目錄;隨機化檔名;提供下載時設定 Content-Disposition: attachment。
  6. 安全 Header 完整部署:X-Frame-Options: DENY、X-Content-Type-Options: nosniff、Referrer-Policy: strict-origin-when-cross-origin、Permissions-Policy 等。

整合建議

  • 將 S 類封裝為 SecurityHelper,註冊為服務容器單例。
  • 在框架 Request 物件建構時,自動對所有輸入執行 escapeChar(可配置白名單欄位跳過)。
  • 模板引擎預設使用 htmlEntities,僅在標記為 raw/safe 的變數使用 htmlEscape。
  • 定期掃碼工具(Psalm、PHPStan、RIPS)靜態分析 XSS/SQLi 風險點。

這套工具類雖屬「手動防禦」時代產物,但其設計思路——分類處理、上下文感知、遞迴清理——仍具參考價值。現代專案建議以「框架內建防護 + CSP + 參數化查詢」為主,工具類作為補充與舊碼遷移橋樑。

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