StringEscapeUtils類的轉義與反轉義方法

org.apache.commons.lang.StringEscapeUtils html

類能夠對js sql html xml等代碼進行轉義!用來處理前端js注入代碼 前端

SQL特殊字符轉義

  應該說,您即便沒有處理 HTML 或 JavaScript 的特殊字符,也不會帶來災難性的後果,可是若是不在動態構造 SQL 語句時對變量中特殊字符進行處理,將可能致使程序漏洞、數據盜取、數據破壞等嚴重的安全問題。網絡中有大量講解 SQL 注入的文章,感興趣的讀者能夠搜索相關的資料深刻研究。

  雖然 SQL 注入的後果很嚴重,可是隻要對動態構造的 SQL 語句的變量進行特殊字符轉義處理,就能夠避免這一問題的發生了。來看一個存在安全漏洞的經典例子:

SELECT COUNT(userId)
FROM t_user
WHERE userName='」+userName+」' AND password ='」+password+」';

  以上 SQL 語句根據返回的結果數判斷用戶提供的登陸信息是否正確,若是 userName 變量不通過特殊字符轉義處理就直接合併到 SQL 語句中,黑客就能夠經過將 userName 設置爲 「1' or '1'='1」繞過用戶名/密碼的檢查直接進入系統了。

  因此除非必要,通常建議經過 PreparedStatement 參數綁定的方式構造動態 SQL 語句,由於這種方式能夠避免 SQL 注入的潛在安全問題。可是每每很難在應用中徹底避免經過拼接字符串構造動態 SQL 語句的方式。爲了防止他人使用特殊 SQL 字符破壞 SQL 的語句結構或植入惡意操做,必須在變量拼接到 SQL 語句以前對其中的特殊字符進行轉義處理。Spring 並無提供相應的工具類,您能夠經過 jakarta commons lang 通用類包中(spring/lib/jakarta-commons/commons-lang.jar)的 StringEscapeUtils 完成這一工做:

  清單 4. SqlEscapeExample

package com.baobaotao.escape;
import org.apache.commons.lang.StringEscapeUtils;
public class SqlEscapeExample {
  public static void main(String[] args) {
    String userName = 」1' or '1'='1」;
    String password = 」123456」;
    userName = StringEscapeUtils.escapeSql(userName);
    password = StringEscapeUtils.escapeSql(password);
    String sql = 」SELECT COUNT(userId) FROM t_user WHERE userName='」
      + userName + 」' AND password ='」 + password + 」'」;
    System.out.println(sql);
  }
}

  事實上,StringEscapeUtils 不但提供了 SQL 特殊字符轉義處理的功能,還提供了 HTML、XML、JavaScript、Java 特殊字符的轉義和還原的方法。若是您不介意引入 jakarta commons lang 類包,咱們更推薦您使用 StringEscapeUtils 工具類完成特殊字符轉義處理的工做。 spring

 

 

------------------------------ sql

 方法入參檢測工具類

  Web 應用在接受表單提交的數據後都須要對其進行合法性檢查,若是表單數據不合法,請求將被駁回。相似的,當咱們在編寫類的方法時,也經常須要對方法入參進行合法性檢查,若是入參不符合要求,方法將經過拋出異常的方式拒絕後續處理。舉一個例子:有一個根據文件名獲取輸入流的方法:InputStream getData(String file),爲了使方法可以成功執行,必須保證 file 入參不能爲 null 或空白字符,不然根本無須進行後繼的處理。這時方法的編寫者一般會在方法體的最前面編寫一段對入參進行檢測的代碼,以下所示:

public InputStream getData(String file) {
  if (file == null || file.length() == 0|| file.replaceAll(」s」, 」」).length() == 0) {
    throw new IllegalArgumentException(」file入參不是有效的文件地址」);
  }

}

  相似以上檢測方法入參的代碼是很是常見,可是在每一個方法中都使用手工編寫檢測邏輯的方式並非一個好主意。閱讀 Spring 源碼,您會發現 Spring 採用一個 org.springframework.util.Assert 通用類完成這一任務。

  Assert 翻譯爲中文爲「斷言」,使用過 JUnit 的讀者都熟知這個概念,它判定某一個實際的運行值和預期想同樣,不然就拋出異常。Spring 對方法入參的檢測借用了這個概念,其提供的 Assert 類擁有衆多按規則對方法入參進行斷言的方法,能夠知足大部分方法入參檢測的要求。這些斷言方法在入參不知足要求時就會拋出 IllegalArgumentException。下面,咱們來認識一下 Assert 類中的經常使用斷言方法:


斷言方法     說明 
notNull(Object object)     當 object 不爲 null 時拋出異常,notNull(Object object, String message) 方法容許您經過 message 定製異常信息。和 notNull() 方法斷言規則相反的方法是 isNull(Object object)/isNull(Object object, String message),它要求入參必定是 null; 
isTrue(boolean expression) / isTrue(boolean expression, String message)     當 expression 不爲 true 拋出異常; 
notEmpty(Collection collection) / notEmpty(Collection collection, String message)     當集合未包含元素時拋出異常。notEmpty(Map map) / notEmpty(Map map, String message) 和 notEmpty(Object[] array, String message) / notEmpty(Object[] array, String message) 分別對 Map 和 Object[] 類型的入參進行判斷; 
hasLength(String text) / hasLength(String text, String message)     當 text 爲 null 或長度爲 0 時拋出異常; 
hasText(String text) / hasText(String text, String message)     text 不能爲 null 且必須至少包含一個非空格的字符,不然拋出異常; 
isInstanceOf(Class clazz, Object obj) / isInstanceOf(Class type, Object obj, String message)     若是 obj 不能被正確造型爲 clazz 指定的類將拋出異常; 
isAssignable(Class superType, Class subType) / isAssignable(Class superType, Class subType, String message)     subType 必須能夠按類型匹配於 superType,不然將拋出異常; 



  使用 Assert 斷言類能夠簡化方法入參檢測的代碼,如 InputStream getData(String file) 在應用 Assert 斷言類後,其代碼能夠簡化爲如下的形式:

public InputStream getData(String file){
  Assert.hasText(file,」file入參不是有效的文件地址」);
  ① 使用 Spring 斷言類進行方法入參檢測

}

  可見使用 Spring 的 Assert 替代自編碼實現的入參檢測邏輯後,方法的簡潔性獲得了很多的提升。Assert 不依賴於 Spring 容器,您能夠大膽地在本身的應用中使用這個工具類 express

--------------code-------------- apache

 

  • import org.apache.commons.lang.StringEscapeUtils;  
  • public class EscapeString {  
  •     public static void main(String[] args) throws Exception {  
  •         String str = "中國";  
  •         System.out.println("用escapeJava方法轉義以後的字符串爲:"+StringEscapeUtils.escapeJava(str));  
  •         System.out.println("用unescapeJava方法反轉義以後的字符串爲:"+StringEscapeUtils.unescapeJava(StringEscapeUtils.escapeJava(str)));  
  •           
  •         System.out.println("用escapeHtml方法轉義以後的字符串爲:"+StringEscapeUtils.escapeHtml(str));  
  •         System.out.println("用unescapeHtml方法反轉義以後的字符串爲:"+StringEscapeUtils.unescapeHtml(StringEscapeUtils.escapeHtml(str)));  
  •           
  •         System.out.println("用escapeXml方法轉義以後的字符串爲:"+StringEscapeUtils.escapeXml(str));  
  •         System.out.println("用unescapeXml方法反轉義以後的字符串爲:"+StringEscapeUtils.unescapeXml(StringEscapeUtils.escapeXml(str)));  
  •           
  •         System.out.println("用escapeJavaScript方法轉義以後的字符串爲:"+StringEscapeUtils.escapeJavaScript(str));  
  •         System.out.println("用unescapeJavaScript方法反轉義以後的字符串爲:"+StringEscapeUtils.unescapeJavaScript(StringEscapeUtils.escapeJavaScript(str)));  
  •         /**輸出結果以下: 
  •          用escapeJava方法轉義以後的字符串爲:/u4E2D/u56FD/u5171/u4EA7/u515A 
  •         用unescapeJava方法反轉義以後的字符串爲:中國
  •         用escapeHtml方法轉義以後的字符串爲:中國
  •         用unescapeHtml方法反轉義以後的字符串爲:中國
  •         用escapeXml方法轉義以後的字符串爲:中國
  •         用unescapeXml方法反轉義以後的字符串爲:中國
  •         用escapeJavaScript方法轉義以後的字符串爲:/u4E2D/u56FD/u5171/u4EA7/u515A 
  •         用unescapeJavaScript方法反轉義以後的字符串爲:中國*/  
  •     }  
  • }  
相關文章
相關標籤/搜索