PHP對錶單提交特殊字符的過濾和處理

前天天緣把博客文章做過一次內容批量修改,由於在源程序存在BUG,導致很多路徑或代碼中的反斜槓被無辜去除,昨天通過bankw3000網友的留言才發現這個問題,已做了部分修正不排除還有些路徑存在問題,如果大家發現博客上存在路徑丟失反斜槓\的問題,歡迎留言反饋,天緣會再做修正。天緣本文特別把PHP關於表單提交特殊字符的處理方法做個彙總,主要涉及htmlspecialchars/addslashes/stripslashes/strip_tags/mysql_real_escape_string等幾個函數聯合使用,與大家共同交流。

一、幾個與特殊字符處理有關的PHP函數

 函數名  釋義  介紹
htmlspecialchars 將與、單雙引號、大於和小於號化成HTML格式 &轉成& 
"轉成"
' 轉成'
<轉成&lt;
>轉成&gt;
htmlentities() 所有字符都轉成HTML格式 除上面htmlspecialchars字符外,還包括雙字節字符顯示成編碼等。
     
addslashes 單雙引號、反斜線及NULL加上反斜線轉義 被改的字符包括單引號 (')、雙引號 (")、反斜線 backslash (\) 以及空字符NULL。
stripslashes 去掉反斜線字符 去掉字符串中的反斜線字符。若是連續二個反斜線,則去掉一個,留下一個。若只有一個反斜線,就直接去掉。
     
quotemeta 加入引用符號 將字符串中含有 . \\ + * ? [ ^ ] ( $ ) 等字符的前面加入反斜線 "\" 符號。
nl2br() 將換行字符轉成<br>  
strip_tags 去掉HTML及PHP標記 去掉字符串中任何 HTML標記和PHP標記,包括標記封堵之間的內容。注意如果字符串HTML及PHP標籤存在錯誤,也會返回錯誤。
mysql_real_escape_string 轉義SQL字符串中的特殊字符 轉義 \x00  \n  \r  空格  \  '  " \x1a,針對多字節字符處理很有效。mysql_real_escape_string會判斷字符集,mysql_escape_string則不用考慮。

其它字符串處理函數,請參考:PHP常用字符串正則替換及 剖分函數比較

下面針對常用表單特殊字符處理進行總結:

測試字符串:

1 $dbstr='D:\test
3 \'!=\'1\' OR \'1\'
4 </DIV>
5 <script  language="javascript" type="text/javascript">alert("Fail");</script>
6  
7  
8 <?php echo "<br/>PHP OUTPUT"; ?>';

測試代碼:

01 header("Content-Type: text/html; charset=UTF-8");
02 echo "------------------------------------------------------<br/>\r\n";
03 echo  $dbstr."<br/>\r\n------------------------------------------------------<br/>\r\n";
04 $str=fnAddSlashes($_POST['dd']);
05 echo $str."<br/>\r\n------------------------------------------------------<br/>\r\n";
06  
07 $str = preg_replace("/\s(?=\s)/","\\1",$str);//多個連續空格只保留一個
08 $str = str_replace("\r","<br/>",$str);
09 $str = str_replace("\n","<br/>",$str);
10 $str = preg_replace("/((<br\/?>)+)/i", "<br/>", $str);//多個連續<br/>標籤只保留一個
11  
12 $str=stripslashes($str);
13 echo strip_tags($str)."<br/>\r\n------------------------------------------------------<br/>\r\n";
14 echo htmlspecialchars($str)."<br/>\r\n------------------------------------------------------<br/>\r\n";
15 echo htmlentities($str)."<br/>\r\n------------------------------------------------------<br/>\r\n";
16 echo mysql_escape_string($str)."<br/>\r\n------------------------------------------------------<br/>\r\n";

字符串包含:反斜槓路徑,單雙引號,HTML標記、鏈接、未封堵的HTML標記,數據庫語法容錯,JS執行判斷,PHP執行判斷,多個連續回車換行符和空格。其中有些概念有包含關係,下同。

源碼輸出如下(會執行JS腳本):

二、表單提交數據處理

1、強制加入反斜線

由於有些主機默認開啓魔術引用get_magic_quotes_gpc,有些可能關閉,所以在程序上最好一律強制加入反斜線,這樣可以統一處理,字符涉及單引號、雙引號和反斜線。

1 function fnAddSlashes($data)
2 {
3     if(!get_magic_quotes_gpc()) //只對POST/GET/cookie過來的數據增加轉義
4         return is_array($data)?array_map('addslashes',$data):addslashes($data);
5     else
6         return $data;
7 }

使用函數fnAddSlashes($data);結果如下圖(不會執行JS腳本,但HTML、JS和PHP標記仍需容錯處理):

使用stripslashes、換行替換、空格替換後結果如下圖:

2、對特殊字符處理

以下是幾個常用字符串處理,可以視具體情況取捨。由於上面已經對提交表單數據進行一次轉義,所以如果需要對內容替換或過濾需要考慮addslashes對相關字符的影響,替換或查找時需考慮反斜槓的添加。其它字符替換不影響,比如\r\n替換。

A、多個連續空格只保留一個

$data = preg_replace("/\s(?=\s)/","\\1",$data );//多個連續空格只保留一個

B、回車換行替換成<br/>
$data = str_replace("\r","<br/>",$data );
$data = str_replace("\n","<br/>",$data );

//html中默認<br>沒封堵,xhtml中<br/>有封堵,建議使用<br/>,更多區別:http://stackoverflow.com/questions/1946426/html-5-is-it-br-br-or-br

C、多個連續<br/>只保留一個

$data = preg_replace("/((<br\/?>)+)/i", "<br/>", $data );//多個連續<br/>標籤只保留一個
 

D、全部過濾HTML標記

該方式是全部過濾潛在危險的標記,包括HTML、鏈接、未封堵HTML標記、JS、PHP。

使用函數strip_tags($data)

該函數使用後會過濾全部的HTML標記(包括鏈接)和PHP標記、JS代碼等,其中鏈接會保留鏈接原文只是去除<a>標記和href部分內容,PHP標記和JS標記則會整體去除,包括中間的內容,如下圖:

E、不過濾標記,只是把他們HTML化

該方法是把原提交內容全部按照普通文本來處理。

使用函數htmlspecialchars($data),該函數執行後會把提交數據全部按照普通文本來展示,如下圖:

使用htmlentities函數執行結果(中文顯示亂碼):

三、寫入數據庫

由於使用addslashes($data)後對於高級的可信任用戶可以直接寫入數據庫,但是addslashes無法攔截使用0xbf27代替的 單引號,所以最好還是使用mysql_real_escape_string或mysql_escape_string進行轉義,不過轉義之前需先去除反 斜槓(假設已默認開啓addslashes)。

01 function fnEscapeStr($data)
02  
03 {
04  
05 if (get_magic_quotes_gpc())
06 {
07         $data= stripslashes($value);
08 }
09 $data="'". mysql_escape_string($value) ."'";
10 return $data;
11 }
12  
13 $data=fnEscapeStr($data);

執行後如下圖:

四、提交後的即時顯示

1、如果上文使用了addslashes,則必須在把數據回顯之前去除反斜線

使用函數stripslashes($data)

注意這個函 數只是面向被addslashes($data)處理後的數據,要謹慎使用,否則會導致反斜線丟失(比如內容的文件夾路徑分割線、驅動器路徑等),天緣前 幾天出現的錯誤就是因爲在數據庫讀取時使用了這個函數(代碼是老代碼,忘記修改了)導致再次寫入數據庫導致很多路徑中的反斜槓丟失,要不也沒有本文了。

2、使用函數htmlspecialchars($data),該函數執行後會把提交數據全部按照文本來展示,除非允許鏈接等需特殊處理外,可以一 律使用 htmlspecialchars輸出,尤其是對於未封堵的HTML標記,如果既沒有過濾再不採用標記轉換,那麼輸出後可能會導致版面混亂。

htmlentities則不建議使用,一方面對輸出的源碼造成很大的閱讀障礙,再者使用htmlentities函數會造成雙字節字符比如中文會顯示一堆亂碼。其它字符顯示還算正常。

第二種輸出方法,視情況需要,如果確認沒有非法標記或潛在的執行風險,可以直接輸出。 

參考資料:http://www.w3school.com.cn/

 

原文鏈接:http://www.metsky.com/archives/377.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章