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

CodeIgniter「URI 提交包含不允許字符」錯誤徹底解決:配置、正則與安全最佳實踐

     編輯:PHP 相關知識

錯誤現象

An Error Was Encountered
The URI you submitted has disallowed characters.

訪問類似 /search/q=php+mysql/@user 或 /api/v1/users/email@domain.com 時觸發。

根本原因

CodeIgniter 預設在 application/config/config.php 中限制 URI 允許字符:

$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-';

任何不在該白名單內的字符(如 @、#、[、]、中文、Emoji)都會被 CI_URI::_filter_uri() 拒絕。

解決方案對比

方案代碼優點缺點/風險
擴展白名單(最常用)
$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-\@';
簡單、即時生效、無代碼侵入 過度放寬可能引入 XSS/注入風險
關閉過濾(不推薦)
$config['permitted_uri_chars'] = '';
完全兼容任意字符 繞過框架安全防線,極易導致漏洞
路由重寫 + Query String
$route['search/(:any)'] = 'search/index/$1';
並用 $_GET['q'] 獲取
乾淨 URL,參數在 Query String,天然安全 需修改路由、前端鏈接生成邏輯
Base64/URL 編碼傳參
$url = 'search/q/' . rawurlencode($keyword);
不改配置,字符安全 URL 變長、可讀性差、需解碼

推薦配置:最小必要擴展

// application/config/config.php
$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-@\+'; // 僅加 @ 和 +
// 解釋:
// a-z 0-9      字母數字
// ~%.:_\-      波浪線、百分號、點、冒號、下劃線、連字符(預設)
// @            郵箱、用戶名常用
// +            空格編碼、搜索詞常用

原則:只添加業務確實需要的字符,避免添加 ' " < > { } | \ ^ ` [ ] 等高風險字符。

進階:自定義 URI 過濾器(CI 3.x)

若需複雜驗證(如只允許特定路由段包含 @),可擴展 CI_URI:

<?php
// application/core/MY_URI.php
class MY_URI extends CI_URI {
    protected function _filter_uri($str)
    {
        // 針對特定控制器/方法放寬
        if (isset($this->segments[1]) && $this->segments[1] === 'api') {
            // API 版本段允許點、連字符、下劃線
            return parent::_filter_uri($str); // 繼承默認邏輯
        }
        // 全局放寬 @
        $config =& get_config();
        $permitted = $config['permitted_uri_chars'] . '@';
        return parent::_filter_uri($str); // 實際需覆寫父類私有方法,建議改配置
    }
}

注意:_filter_uri 為 private,無法直接覆寫。最佳實踐仍是修改配置或調整 URL 設計。

安全檢查清單

  1. 修改配置後,立即測試:/test/@#$% 應報錯,/test/user@domain 應通過。
  2. 確認 $config['enable_query_strings'] = FALSE(預設),避免雙重解析混淆。
  3. 所有輸出到視圖的 URI 片段,必須經 html_escape() 或 xss_clean()。
  4. 控制器中使用 $this->uri->segment(n) 獲取參數,而非直接 $_GET。
  5. 定期掃描日誌中的 Disallowed characters 錯誤,分析是否為攻擊探測。

遷移到 CI4 的差異

CodeIgniter 4 棄用 permitted_uri_chars,改用路由正則約束:

// app/Config/Routes.php
$routes->get('search/(:segment)', 'Search::index/$1'); // :segment 預設 [^/]+
$routes->get('user/(:any)', 'User::profile/$1');       // :any 匹配任意含 /
// 自定義正則
$routes->add('email/(:segment)', 'User::byEmail/$1', ['as' => 'user.email'])
       ->where('segment', '[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}');

CI4 更靈活、更安全,建議新專案直接使用 CI4。

總結

「URI 包含不允許字符」是 CodeIgniter 內建的安全防線。解決之道:**最小化擴展白名單**、**優先調整 URL 設計(Query String/路由)**、**嚴禁關閉過濾**。配合輸出轉義、輸入驗證、日誌審計,構建纵深防禦。

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