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方法反转义以后的字符串为:中国*/  
  •     }  
  • }  
相关文章
相关标签/搜索