The important thing in life is to have a great aim , and the determination

          常用鏈接

          統(tǒng)計

          IT技術鏈接

          保險相關

          友情鏈接

          基金知識

          生活相關

          最新評論

          特殊字符的轉(zhuǎn)義


        1. 特殊字符轉(zhuǎn)義   
        2.   
        3. 由于 Web 應用程序需要聯(lián)合使用到多種語言,每種語言都包含一些特殊的字符,對于動態(tài)語言或標簽式的語言而言,如果需要動態(tài)構造語言的內(nèi)容時,一個我們經(jīng)常會碰到的問題就是特殊字符轉(zhuǎn)義的問題。下面是 Web 開發(fā)者最常面對需要轉(zhuǎn)義的特殊字符類型:   
        4.   
        5. HTML 特殊字符;    
        6. JavaScript 特殊字符;    
        7. SQL 特殊字符;    
        8. 如果不對這些特殊字符進行轉(zhuǎn)義處理,則不但可能破壞文檔結構,還可以引發(fā)潛在的安全問題。Spring 為 HTML 和 JavaScript 特殊字符提供了轉(zhuǎn)義操作工具類,它們分別是 HtmlUtils 和 JavaScriptUtils。   
        9.   
        10. HTML 特殊字符轉(zhuǎn)義   
        11.   
        12. HTML 中 <,>,& 等字符有特殊含義,它們是 HTML 語言的保留字,因此不能直接使用。使用這些個字符時,應使用它們的轉(zhuǎn)義序列:   
        13.   
        14. &:&    
        15. " :"    
        16. < :<    
        17. > :>    
        18. 由于 HTML 網(wǎng)頁本身就是一個文本型結構化文檔,如果直接將這些包含了 HTML 特殊字符的內(nèi)容輸出到網(wǎng)頁中,極有可能破壞整個 HTML 文檔的結構。所以,一般情況下需要對動態(tài)數(shù)據(jù)進行轉(zhuǎn)義處理,使用轉(zhuǎn)義序列表示 HTML 特殊字符。下面的 JSP 網(wǎng)頁將一些變量動態(tài)輸出到 HTML 網(wǎng)頁中:   
        19.   
        20.   
        21. 清單 1. 未進行 HTML 特殊字符轉(zhuǎn)義處理網(wǎng)頁   
        22.                    
        23. <%@ page language="java" contentType="text/html; charset=utf-8"%>   
        24. <%!   
        25.    String userName = "</td><tr></table>";   
        26.    String address = " \" type=\"button";   
        27.  %>   
        28. <table border="1">   
        29.    <tr>   
        30.      <td>姓名:</td><td><%=userName%></td> ①   
        31.    </tr>   
        32.    <tr>   
        33.      <td>年齡:</td><td>28</td>   
        34.    </tr>   
        35. </table>   
        36.  <input value="<%=address%>"  type="text" /> ②   
        37.     
        38.   
        39.   
        40. 在 ① 和 ② 處,我們未經(jīng)任何轉(zhuǎn)義處理就直接將變量輸出到 HTML 網(wǎng)頁中,由于這些變量可能包含一些特殊的 HTML 的字符,它們將可能破壞整個 HTML 文檔的結構。我們可以從以上 JSP 頁面的一個具體輸出中了解這一問題:   
        41.   
        42. <table border="1">   
        43.    <tr>   
        44.      <td>姓名:</td><td></td><tr></table></td>    
        45.      ① 破壞了 <table> 的結構   
        46.    </tr>   
        47.    <tr>   
        48.      <td>年齡:</td><td>28</td>   
        49.    </tr>   
        50. </table>   
        51.  <input value=" " type="button"  type="text" />    
        52.  ② 將本來是輸入框組件偷梁換柱為按鈕組件   
        53.     
        54.   
        55.   
        56. 融合動態(tài)數(shù)據(jù)后的 HTML 網(wǎng)頁已經(jīng)面目全非,首先 ① 處的 <table> 結構被包含 HTML 特殊字符的 userName 變量截斷了,造成其后的 <table> 代碼變成無效的內(nèi)容;其次,② 處 <input> 被動態(tài)數(shù)據(jù)改換為按鈕類型的組件(type="button")。為了避免這一問題,我們需要事先對可能破壞 HTML 文檔結構的動態(tài)數(shù)據(jù)進行轉(zhuǎn)義處理。Spring 為我們提供了一個簡單適用的 HTML 特殊字符轉(zhuǎn)義工具類,它就是 HtmlUtils。下面,我們通過一個簡單的例子了解 HtmlUtils 的具體用法:   
        57.   
        58.   
        59. 清單 2. HtmpEscapeExample   
        60.                    
        61. package com.baobaotao.escape;   
        62. import org.springframework.web.util.HtmlUtils;   
        63. public class HtmpEscapeExample {   
        64.     public static void main(String[] args) {   
        65.         String specialStr = "<div id=\"testDiv\">test1;test2</div>";   
        66.         String str1 = HtmlUtils.htmlEscape(specialStr); ①轉(zhuǎn)換為HTML轉(zhuǎn)義字符表示   
        67.         System.out.println(str1);   
        68.           
        69.         String str2 = HtmlUtils.htmlEscapeDecimal(specialStr); ②轉(zhuǎn)換為數(shù)據(jù)轉(zhuǎn)義表示   
        70.         System.out.println(str2);   
        71.           
        72.         String str3 = HtmlUtils.htmlEscapeHex(specialStr); ③轉(zhuǎn)換為十六進制數(shù)據(jù)轉(zhuǎn)義表示   
        73.         System.out.println(str3);   
        74.           
        75.         ④下面對轉(zhuǎn)義后字符串進行反向操作   
        76.         System.out.println(HtmlUtils.htmlUnescape(str1));   
        77.         System.out.println(HtmlUtils.htmlUnescape(str2));   
        78.         System.out.println(HtmlUtils.htmlUnescape(str3));   
        79.     }   
        80. }   
        81.     
        82.   
        83.   
        84. HTML 不但可以使用通用的轉(zhuǎn)義序列表示 HTML 特殊字符,還可以使用以 # 為前綴的數(shù)字序列表示 HTML 特殊字符,它們在最終的顯示效果上是一樣的。HtmlUtils 提供了三個轉(zhuǎn)義方法:   
        85.   
        86. 方法 說明    
        87. static String htmlEscape(String input)  將 HTML 特殊字符轉(zhuǎn)義為 HTML 通用轉(zhuǎn)義序列;    
        88. static String htmlEscapeDecimal(String input)  將 HTML 特殊字符轉(zhuǎn)義為帶 # 的十進制數(shù)據(jù)轉(zhuǎn)義序列;    
        89. static String htmlEscapeHex(String input)  將 HTML 特殊字符轉(zhuǎn)義為帶 # 的十六進制數(shù)據(jù)轉(zhuǎn)義序列;    
        90.   
        91. 此外,HtmlUtils 還提供了一個能夠?qū)⒔?jīng)過轉(zhuǎn)義內(nèi)容還原的方法:htmlUnescape(String input),它可以還原以上三種轉(zhuǎn)義序列的內(nèi)容。運行以上代碼,您將可以看到以下的輸出:   
        92.   
        93. str1:<div id="testDiv">test1;test2</div>   
        94. str2:<div id="testDiv">test1;test2</div>   
        95. str3:<div id="testDiv">test1;test2</div>   
        96. <div id="testDiv">test1;test2</div>   
        97. <div id="testDiv">test1;test2</div>   
        98. <div id="testDiv">test1;test2</div>   
        99.     
        100.   
        101.   
        102. 您只要使用 HtmlUtils 對代碼 清單 1 的 userName 和 address 進行轉(zhuǎn)義處理,最終輸出的 HTML 頁面就不會遭受破壞了。   
        103.   
        104. JavaScript 特殊字符轉(zhuǎn)義   
        105.   
        106. JavaScript 中也有一些需要特殊處理的字符,如果直接將它們嵌入 JavaScript 代碼中,JavaScript 程序結構將會遭受破壞,甚至被嵌入一些惡意的程序。下面列出了需要轉(zhuǎn)義的特殊 JavaScript 字符:   
        107.   
        108. ' :\'    
        109. " :\"    
        110. \ :\\    
        111. 走紙換頁: \f    
        112. 換行:\n    
        113. 換欄符:\t    
        114. 回車:\r    
        115. 回退符:\b    
        116. ?    
        117. 我們通過一個具體例子演示動態(tài)變量是如何對 JavaScript 程序進行破壞的。假設我們有一個 JavaScript 數(shù)組變量,其元素值通過一個 Java List 對象提供,下面是完成這一操作的 JSP 代碼片斷:   
        118.   
        119.   
        120. 清單 3. jsTest.jsp:未對 JavaScript 特殊字符進行處理   
        121.                    
        122. <%@ page language="java" contentType="text/html; charset=utf-8"%>   
        123. <jsp:directive.page import="java.util.*"/>   
        124. <%   
        125.   List textList = new ArrayList();   
        126.   textList.add("\";alert();j=\"");   
        127. %>   
        128. <script>   
        129.   var txtList = new Array();   
        130.    <% for ( int i = 0 ; i < textList.size() ; i++) { %>   
        131.      txtList[<%=i%>] = "<%=textList.get(i)%>";    
        132.      ① 未對可能包含特殊 JavaScript 字符的變量進行處理   
        133.    <% } %>   
        134. </script>   
        135.     
        136.   
        137.   
        138. 當客戶端調(diào)用這個 JSP 頁面后,將得到以下的 HTML 輸出頁面:   
        139.   
        140. <script>   
        141.   var txtList = new Array();   
        142.    txtList[0] = "";alert();j=""; ① 本來是希望接受一個字符串,結果被植入了一段JavaScript代碼   
        143. </script>   
        144.     
        145.   
        146.   
        147. 由于包含 JavaScript 特殊字符的 Java 變量直接合并到 JavaScript 代碼中,我們本來期望 ① 處所示部分是一個普通的字符串,但結果變成了一段 JavaScript 代碼,網(wǎng)頁將彈出一個 alert 窗口。想像一下如果粗體部分的字符串是“";while(true)alert();j="”時會產(chǎn)生什么后果呢?   
        148.   
        149. 因此,如果網(wǎng)頁中的 JavaScript 代碼需要通過拼接 Java 變量動態(tài)產(chǎn)生時,一般需要對變量的內(nèi)容進行轉(zhuǎn)義處理,可以通過 Spring 的 JavaScriptUtils 完成這件工作。下面,我們使用 JavaScriptUtils 對以上代碼進行改造:   
        150.   
        151. <%@ page language="java" contentType="text/html; charset=utf-8"%>   
        152. <jsp:directive.page import="java.util.*"/>   
        153. <jsp:directive.page import="org.springframework.web.util.JavaScriptUtils"/>   
        154. <%   
        155.   List textList = new ArrayList();   
        156.   textList.add("\";alert();j=\"");   
        157. %>   
        158. <script>   
        159.    var txtList = new Array();   
        160.    <% for ( int i = 0 ; i < textList.size() ; i++) { %>   
        161.    ① 在輸出動態(tài)內(nèi)容前事先進行轉(zhuǎn)義處理   
        162.    txtList[<%=i%>] = "<%=JavaScriptUtils.javaScriptEscape(""+textList.get(i))%>";   
        163.    <% } %>   
        164. </script>   
        165.     
        166.   
        167.   
        168. 通過轉(zhuǎn)義處理后,這個 JSP 頁面輸出的結果網(wǎng)頁的 JavaScript 代碼就不會產(chǎn)生問題了:   
        169.   
        170. <script>   
        171.    var txtList = new Array();   
        172.    txtList[0] = "\";alert();j=\"";   
        173.    ① 粗體部分僅是一個普通的字符串,而非一段 JavaScript 的語句了   
        174. </script>   
        175.     
        176.   
        177.   
        178. SQL特殊字符轉(zhuǎn)義   
        179.   
        180. 應該說,您即使沒有處理 HTML 或 JavaScript 的特殊字符,也不會帶來災難性的后果,但是如果不在動態(tài)構造 SQL 語句時對變量中特殊字符進行處理,將可能導致程序漏洞、數(shù)據(jù)盜取、數(shù)據(jù)破壞等嚴重的安全問題。網(wǎng)絡中有大量講解 SQL 注入的文章,感興趣的讀者可以搜索相關的資料深入研究。   
        181.   
        182. 雖然 SQL 注入的后果很嚴重,但是只要對動態(tài)構造的 SQL 語句的變量進行特殊字符轉(zhuǎn)義處理,就可以避免這一問題的發(fā)生了。來看一個存在安全漏洞的經(jīng)典例子:   
        183.   
        184. SELECT COUNT(userId)    
        185. FROM t_user    
        186. WHERE userName='"+userName+"' AND password ='"+password+"';   
        187.     
        188.   
        189.   
        190. 以上 SQL 語句根據(jù)返回的結果數(shù)判斷用戶提供的登錄信息是否正確,如果 userName 變量不經(jīng)過特殊字符轉(zhuǎn)義處理就直接合并到 SQL 語句中,黑客就可以通過將 userName 設置為 “1' or '1'='1”繞過用戶名/密碼的檢查直接進入系統(tǒng)了。   
        191.   
        192. 所以除非必要,一般建議通過 PreparedStatement 參數(shù)綁定的方式構造動態(tài) SQL 語句,因為這種方式可以避免 SQL 注入的潛在安全問題。但是往往很難在應用中完全避免通過拼接字符串構造動態(tài) SQL 語句的方式。為了防止他人使用特殊 SQL 字符破壞 SQL 的語句結構或植入惡意操作,必須在變量拼接到 SQL 語句之前對其中的特殊字符進行轉(zhuǎn)義處理。Spring 并沒有提供相應的工具類,您可以通過 jakarta commons lang 通用類包中(spring/lib/jakarta-commons/commons-lang.jar)的 StringEscapeUtils 完成這一工作:   
        193.   
        194.   
        195. 清單 4. SqlEscapeExample   
        196.                    
        197. package com.baobaotao.escape;   
        198. import org.apache.commons.lang.StringEscapeUtils;   
        199. public class SqlEscapeExample {   
        200.     public static void main(String[] args) {   
        201.         String userName = "1' or '1'='1";   
        202.         String password = "123456";   
        203.         userName = StringEscapeUtils.escapeSql(userName);   
        204.         password = StringEscapeUtils.escapeSql(password);   
        205.         String sql = "SELECT COUNT(userId) FROM t_user WHERE userName='"  
        206.             + userName + "' AND password ='" + password + "'";   
        207.         System.out.println(sql);   
        208.     }   
        209. }   
        210.     
        211.   
        212.   
        213. 事實上,StringEscapeUtils 不但提供了 SQL 特殊字符轉(zhuǎn)義處理的功能,還提供了 HTML、XML、JavaScript、Java 特殊字符的轉(zhuǎn)義和還原的方法。如果您不介意引入 jakarta commons lang 類包,我們更推薦您使用 StringEscapeUtils 工具類完成特殊字符轉(zhuǎn)義處理的工作。   

        214. posted on 2011-01-24 14:16 鴻雁 閱讀(3854) 評論(0)  編輯  收藏 所屬分類: IT技術相關

          主站蜘蛛池模板: 舟山市| 富源县| 文成县| 茂名市| 禹州市| 呼伦贝尔市| 涟源市| 响水县| 浮梁县| 射洪县| 丰台区| 大邑县| 灵台县| 仪陇县| 措美县| 景洪市| 山东| 扬州市| 贵阳市| 贵州省| 林西县| 云和县| 九寨沟县| 开阳县| 罗甸县| 博兴县| 利津县| 唐山市| 叶城县| 平阴县| 大名县| 公安县| 繁峙县| 青神县| 天津市| 黑河市| 德格县| 寻甸| 贺州市| 博客| 射洪县|