原創做品author流水孟春,轉載請註明出處lib.cublog.cn
php
閱讀前提:你必須看過php手冊上的"第IV部分安全"的"第10章魔術引號"。若是沒看過,也沒問題,如今立刻花10分鐘先看一下php手冊上的這東西。魔術引號(Magic Quote)是一個自動將進入 PHP 腳本的數據進行轉義的過程
mysql
你可能想讓你的程序兼容多個數據庫,但你使用的不一樣的數據庫可能使用不一樣的轉義符,而咱們的程序又有可能運行在不一樣的php.ini配置的主機上,關於magic_quotes的配置又可能不同,因此編寫不受魔術引號影響的php應用是高兼容性的php應用所必須的。
php.ini中有三個魔術引號配置選項:
sql
魔術引號配置選項 | 描述 | 運行時改變 | 在 PHP中的默認值爲 |
magic_quotes_gpc | 若是打開的話,影響到 HTTP 請求數據(GET,POST 和 COOKIE)。 | 不能 | On |
magic_quotes_runtime | 若是打開的話,大部份從外部來源取得數據並返回的函數,包括從數據庫和文本文件,所返回的數據都會被反斜線轉義。(前提是magic_quotes_gpc = On) | 能 | Off |
magic_quotes_sybase | 當關閉時,全部的 '(單引號),"(雙引號),/(反斜線)和 NULL 字符都會被自動加上一個反斜線進行轉義。這和 addslashes() 做用徹底相同。 |
能 | Off |
可是要處理外部傳來的全局變量就比較麻煩了。
安全
要 處理外部超級變量,咱們要看magic_quotes_gpc是否已經打開(若是magic_quotes_gpc沒打開,而 magic_quotes_sybase打開,magic_quotes_sybase也不起做用),還要看magic_quotes_sybase是否 打開,再看咱們的程序須要對外部變量用addslashes轉義方式仍是使用magic_quotes_sybase式的轉義方式。下面的代碼是一個具體 的實現。
函數
有人可能說,當magic_quotes_gpc設成On,而magic_quotes_sybase設成Off,那麼直接用 ini_set('magic_quotes_sybase', 1);就能讓系統用'來對addslashes式的轉義進行覆蓋。這樣是不行的。你用ini_get('magic_quotes_sybase')輸出 看下配置,magic_quotes_sybase的確被改變了,可是你的代碼就是不能用'轉義符覆蓋addslashes式的自動轉義。這是由於系統獲 取外部變量的時候,是在你的ini_set('magic_quotes_sybase', 1);以前完成的。
測試
<?php
spa
/**
* 解決不受magic_quotes影響的php應用
*
* 使用這個處理辦法須要配置是否使用magic_quotes_sybase, 以適應不一樣的DBMS
*
* 設置方法:
* $useQuotesSybase[數據庫名] = 1;
* 如:使用sqlite,則定義並初始化 $useQuotesSybase['sqlite'] = 1;
* 若是使用mysql,能夠定義並初始化 $useQuotesSybase['sqlite'] = 0; 也能夠不定義
*
* CONFIG_DB_DBMS 爲所用的DBMS的常量, 在別處定義。好比 define('CONFIG_DB_DBMS', 'mysql');
*
* @author 流水孟春 cmpan(at)qq.com
* @link http://lib.cublog.cn
* $date 2007.11.18
*/
error_reporting(E_ALL);
set_magic_quotes_runtime(0);
define('CONFIG_DB_DBMS', 'sqlite'); // 測試用
// 使用 ' 作轉義符的數據庫
$useQuotesSybase = array();
$useQuotesSybase['sqlite'] = 1;
$useQuotesSybase['sybase'] = 1;
if(!empty($_POST)) $_POST = array_map('quotesOuterVars', $_POST);
if(!empty($_GET)) $_GET = array_map('quotesOuterVars', $_GET);
$_COOKIE = array_map('quotesOuterVars', $_COOKIE);
$_REQUEST = array_map('quotesOuterVars', $_REQUEST);
function quotesOuterVars($var) {
if (is_array($var)) {
return array_map('quotesOuterVars',$var);
} else {
if (get_magic_quotes_gpc()) {
if (isset($GLOBALS['useQuotesSybase'][CONFIG_DB_DBMS]) && $GLOBALS['useQuotesSybase'][CONFIG_DB_DBMS]) {
// 當前須要以 ' 爲轉義符
// 若是 magic_quotes_sybase = Off, 系統將把外部變量 addslashes, 咱們得先 stripslashes
// 不然系統自動把 ' 換成 '',
if (!ini_get('magic_quotes_sybase')) {
$var = stripslashes($var);
$var = str_replace("'", "''", $var);
}
} else {
// 當前須要以 / 爲轉義符
// 若是 magic_quotes_sybase = On, 咱們先把 '' 替換成 ', 而後在 addslashes
// 不然系統自動quotes
if (ini_get('magic_quotes_sybase')) {
$var = str_replace("'", "''", $var);
$var = addslashes($var);
}
}
} else{
if (isset($GLOBALS['useQuotesSybase'][CONFIG_DB_DBMS]) && $GLOBALS['useQuotesSybase'][CONFIG_DB_DBMS]) {
$var = str_replace("'", "''", $var);
} else {
$var = addslashes($var);
}
}
return trim($var);
.net
}
}
從上面的表咱們能夠看出,對於magic_quotes_runtime,我在程序中用 ini_set('magic_quotes_runtime', 0);就能夠把它關掉,而後能夠用本身的方法來處理來自數據庫或文件的數據。
code