由於PHP程序常常與HTML頁、Web地址(URL)以及數據庫交互,因此PHP提供一些函數來幫助你處理這些類型的數據。HTML、Web頁地址和數據庫命令都是字符串,可是它們每一個都要求不一樣的字符以不一樣的方法來轉義。例如,在Web地址中一個空格被寫成%20,而直接量小於符號(<)在HTML文檔中必須寫做<。PHP有許多內置函數來轉換和取得這些編碼。
HTML:在HTML中特殊的字符以實體(entity)表示,如&和<。這裏有兩個PHP函數來把字符串中的特殊字符轉換爲實體,一個用於刪除HTML標籤,一個僅用於提取meta標籤。
對全部特殊字符進行實體引用:函數htmlentities()將HTML字符轉換爲對應的實體(除了空格符)。包括小於符號(<)、大於符號(>)、與號(&)和重音字符。(entity實體)
只對HTML語法字符進行實體引用:函數htmlspacialchars()轉換最小的實體集來生成合法的HTML。下面的實體被轉換:
與符號(&)被轉換成&
雙引號(")被轉換成"
單引號(')被轉換成'(就像調用htmlentities()時使用ENT_QUOTES的效果)
小於號(<)被轉換成<
大於號(>)被轉換成>
若是有一個應用程序來顯示用戶填入表單的數據,則要在顯示和保存數據以前經過htmlspecialchars()處理數據。若是沒有處理的話,一旦用戶提交了像"angle<30"或"sturm & drang"這樣的字符串,瀏覽器會人爲這些特殊的字符是HTML,從而獲得一個混亂的頁面。
刪除HTML標籤
函數strip_tags()從字符串中刪除HTML標籤:
$input='<p>Howdy,"Cowboy"</p>;
$output=strip_tags($input);//$output是'Howdy,"Cowboy"'
函數能夠有第二個參數來指定在字符串中留下的標籤。之列出標籤的開始形式,在第二個參數中列出的標籤結束形式也將被保留:
$input='The <b>bold</b> tags will<i>stay</i><p>';
$output=strip_tags($input,'<b>');//$output是'The <b>bold</b> tags will stay'
在保留標籤中的屬性不會被strip_tags()改變。因爲HTML標籤屬性(例如style和onmouseover)能夠影響Web頁面的外觀和行爲,因此用strip_tags()保留一些標籤可能會致使沒法刪除全部潛在的冗餘內容。
提取元標籤
若是你把Web頁面的HTML存在一個字符串中,函數get_meta_tags()可返回包含該頁面中元標籤(meta tag)內容的數組。元標籤的名字(keywords、author、escription等)成爲數組的鍵,而元標籤的內容則成爲對應的值:
$meta_tags=get_meta_tags('http://www.example.com/');
echo "Web page made by {$meta_tags[author]}";
函數通常的形式是:
$array=get_meta_tags(filename[,use_include_path]);
能夠指定參數use_include_path爲true,這樣可以使PHP嘗試用標準包含路徑打開文件。
URL:PHP提供了一些函數用於對URL進行編碼和解碼。有兩種方法對URL編碼,其區別在於如何處理空格。第一種(根據RFC1738規範)把空格當作URL中的另外一個非法字符並把它編碼爲%20。第二種(執行application/x-www-form-urlencoded系統)把空格編碼爲一個+而且把它用於創建查詢的字符串中。
注意並不須要對一個完整的URL使用這些函數,例如http://www.example.com/hello,由於它們會轉義冒號和反斜槓:
http%3A%2F%2Fwww.example.com%2Fhello
應該只編碼部分URL(在http://www.example.com/後面的部分),隨後再加上協議和域名。
RFC1738編碼和解碼
要把字符串依照URL約定編碼,可使用rawurlencode():
$output=rawurlencode(input);
該函數接收一個字符串並返回對該字符串的拷貝,該拷貝中把非法URL字符按%dd約定編碼。
若是你要爲一個頁面裏的連接動態生成超級連接地址,則須要用rawurlencode()轉換它們:
$name="Programming PHP";
$output=rawurlencode($name);
echo "http://localhost/$output";
http://localhost/Programming%20PHP
函數rawurldecode()用於解碼被編碼過的URL字符串:
$encoded='Programming%20PHP';
echo rawurldecode($encoded);
Programming PHP
查詢字符串編碼
urlencode()和urldecode()函數和它們原始版本(即rawurlencode()和rawurldecode())的不一樣僅在於它們把空格編碼爲加號(+),而不是%20。這是用於建立查詢字符串(query string)和cookie值的格式,可是由於這些值在經過表單或cookie傳送時會自動解碼,因此你不須要使用這些函數來處理當前頁的查詢字符串或cookie。這兩個函數對於生成查詢字符串是頗有用的:
$base_url='http://www.google.com/q=';
$query='PHP sessions -cookies';
$url=$base_url.urlencode($query);
echo $url;
http://www.google.com/q=PHP+sessions+cookies
SQL:絕大多數數據庫系統都要求將SQL查詢字符串進行轉義。SQL的轉義方法至關簡單——在單引號、雙引號、空字節和反斜槓前面加上一個反斜槓(\)。addslashes()函數可添加這些反斜槓,stripslashes()函數則刪除它們:
$string=<<<The_end
"It's never going to work," she cried,
as she hit the backslash(\)key.
The_End;
echo addslashes($string);
\"It\'s never going to work,\"she cried,
as she hit the backslash (\\) key.
echo stripslashes($string);
"It's never going to work," she cried,
as she hit the backslash (\) key.
提示:一些數據庫(如SYBASE)用另外一個單引號爲單引號轉義,而不是一個反斜槓。對於這些數據庫,能夠在php.ini文件中打開magic_quotes_sybase。php
數據錯誤的以代碼形式執行是漏洞的根本緣由,那麼修復方法固然是讓數據只能以數據的形式被SQL層認識並帶入查詢。
若是沒有用加反斜槓轉義,那麼id=111'相似的查詢條件就會直接帶入查詢語句:select * from table where id='$id'就變成了select * from table where id='111'';查詢語句有未閉合的單引號報錯
而若是咱們使用了函數addslashes()進行反斜槓轉義,那麼SQL查詢語句會變成:select * from table where id='111\'',因此id=111'中的單引號因爲被以\'的形式傳遞,因此會以值的形式執行,SQL就會認爲id=111'中的單引號是id變量值的一部分,那麼查詢結果有可能存在也有可能不存在,(例如,若是存在id爲王二小's的數據庫值,就存在查詢結果),可是最重要的是,單引號在這裏是以值的形式傳遞的,這纔是最最根本的本質。html
1. 對於PHP magic_quotes_gpc=on的狀況,mysql
咱們能夠不對輸入和輸出數據庫的字符串數據做,addslashes()和stripslashes()的操做,數據也會正常顯示。sql
若是此時你對輸入的數據做了addslashes()處理,那麼在輸出的時候就必須使用stripslashes()去掉多餘的反斜槓。數據庫
2. 對於PHP magic_quotes_gpc=off 的狀況,必須使用addslashes()對輸入數據進行處理,但並不須要使用stripslashes()格式化輸出。由於addslashes()並未將反斜槓一塊兒寫入數據庫,只是幫助mysql完成了sql語句的執行。編程
有的網站,外面是能夠設置標籤爲「編程's」等這種格式的,可是一點擊保存,就報錯了,特別搞。而後無論哪一個訪問對應標籤的文章,都會看到這個報錯。這就是因爲從用戶輸入到PHP代碼再到SQL層,其中PHP整合SQL查詢語句時的錯誤編寫形成的。
知識的積累過程,老是起先你不懂,然後學了一點,就顛兒顛兒的覺得「兒得矣」,當有一天你忽然迷茫了,以爲哪兒彷佛沒那麼形而上的通暢,而後你會不自主的想到底哪兒還有問題呢?你會迷茫好久,直到有一天終於找到了那個缺角,而後它是那麼美好由於當你找到的時候就差很少已經有能力填充了。一切便豁然開朗。數組
有的時候,會略顯無奈,由於人們愈來愈浮躁,而安全環境剛創建,安全問題剛獲得更多的重視,因此大多數人在「顛兒顛兒」的階段時,已經被業內大體承認,因此會特別盲目的自信,而有很多人,倒是玩了很久,也沒想到過還有哪兒值得迷茫。眼高手低,永遠是一個讓人崩潰的事實。瀏覽器
有的時候,id數據值會被設置爲intval($id),這種狀況下,若是變量只能是數字,就不會產生注入了,由於無論輸入什麼都會以數字——及值的形式帶入數據庫查詢。然而,若是是字符型id值,並且還用到了addslashes(),是否是就安全了呢?,還真沒有,由於若是sql語句形式是select * from table where id="'$_POST[id]'",這種狀況,id值被單引號包含,咱們要想構造能以代碼執行的惡意值須要閉合前面的單引號,而addslashes會將咱們輸入的單引號轉移爲正常的值形式帶入查詢。這種狀況就呵呵了。好在有的sql語句中參數值沒有用單引號包含,例如:select * from table where id="$_POST[id]",雖然開啓了addslashes轉義單引號等特殊字符,可是咱們根本就不須要單引號閉合sql查詢語句中的id字段,因此照樣能夠注入。安全