前天天緣把博客文章做過一次內容批量修改,由於在源程序存在BUG,導致很多路徑或代碼中的反斜槓被無辜去除,昨天通過bankw3000網友的留言才發現這個問題,已做了部分修正不排除還有些路徑存在問題,如果大家發現博客上存在路徑丟失反斜槓\的問題,歡迎留言反饋,天緣會再做修正。天緣本文特別把PHP關於表單提交特殊字符的處理方法做個彙總,主要涉及htmlspecialchars/addslashes/stripslashes/strip_tags/mysql_real_escape_string等幾個函數聯合使用,與大家共同交流。
一、幾個與特殊字符處理有關的PHP函數
函數名 |
釋義 |
介紹 |
htmlspecialchars |
將與、單雙引號、大於和小於號化成HTML格式 |
&轉成&
"轉成"
' 轉成'
<轉成<
>轉成> |
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常用字符串正則替換及 剖分函數比較。
下面針對常用表單特殊字符處理進行總結:
測試字符串:
5 |
<script language= "javascript" type= "text/javascript" >alert( "Fail" );</script> |
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" ; |
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 ); |
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 ) |
3 |
if (!get_magic_quotes_gpc()) |
4 |
return is_array ( $data )? array_map ( 'addslashes' , $data ): addslashes ( $data ); |
使用函數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 ) |
05 |
if (get_magic_quotes_gpc()) |
07 |
$data = stripslashes ( $value ); |
09 |
$data = "'" . mysql_escape_string( $value ) . "'" ; |
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