sql特殊字符转义处理,防止注入

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

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 工具类完成特殊字符转义处理的工作。

附:commons-lang常用工具类StringEscapeUtils使用

在apache commons-lang(2.3以上版本)中为我们提供了一个方便做转义的工具类,主要是为了防止sql注入,xss注入攻击的功能。


commons-lang常用工具类StringEscapeUtils使用 - wjoygz - pauls private zone


1.escapeSql 提供sql转移功能,防止sql注入攻击,例如典型的万能密码攻击' ' or 1=1 ' '


1StringBuffer sql = new StringBuffer("select key_sn,remark,create_date from tb_selogon_key where 1=1 ");


2if(!CommUtil.isEmpty(keyWord)){


3sql.append(" and like '%" + StringEscapeUtils.escapeSql(keyWord) + "%'");


2.escapeHtml /unescapeHtml  转义/反转义html脚本


1System.out.println(StringEscapeUtils.escapeHtml("dddd"));   


2输出结果为:


dddd


1System.out.println(StringEscapeUtils.unescapeHtml("dddd"));   


2输出为:


ddd


3.escapeJavascript/unescapeJavascript 转义/反转义js脚本


1System.out.println(StringEscapeUtils.escapeJavaScript("


2"));   


3输出为:

4.escapeJava/unescapeJava 把字符串转为unicode编码

1System.out.println(StringEscapeUtils.escapeJava("中国"));   

2输出为:

用escapeJava方法转义之后的字符串为:/u4E2D/u56FD/u5171/u4EA7/u515A

另一个例子:

import org.apache.commons.lang.StringEscapeUtils;  

public class EscapeString {  

    public static void main(String[] args) throws Exception {  

        String str = "APEC召开时不让点柴火做饭";  

        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方法转义之后的字符串为:APEC\u53EC\u5F00\u65F6\u4E0D\u8BA9\u70B9\u67F4\u706B\u505A\u996D


用unescapeJava方法反转义之后的字符串为:APEC召开时不让点柴火做饭


用escapeHtml方法转义之后的字符串为:APEC召开时不让点柴火做饭


用unescapeHtml方法反转义之后的字符串为:APEC召开时不让点柴火做饭


用escapeXml方法转义之后的字符串为:APEC召开时不让点柴火做饭


用unescapeXml方法反转义之后的字符串为:APEC召开时不让点柴火做饭


用escapeJavaScript方法转义之后的字符串为:APEC\u53EC\u5F00\u65F6\u4E0D\u8BA9\u70B9\u67F4\u706B\u505A\u996D


用unescapeJavaScript方法反转义之后的字符串为:APEC召开时不让点柴火做饭


    }  


}  


表单富文本输入时,有html,需要转义,html+加中文时,用StringEscapeUtils.escapeHtml转义时,中文也转义了,经过查找,最终找到spring的org.springframework.web.util.HtmlUtils.htmlEscape

    org.springframework

    spring-webmvc

    3.0.6.RELEASE

public static void main(String[] args) {

    String a = "吃饭";

    System.out.println(StringEscapeUtils.escapeHtml(a));

    System.out.println(StringEscapeUtils.unescapeHtml(StringEscapeUtils.escapeHtml(a)));

    System.out.println(HtmlUtils.htmlEscape(a));

    System.out.println(HtmlUtils.htmlUnescape(HtmlUtils.htmlEscape(a)));

}

执行结果:


<html>吃饭</html>


吃饭


<html>吃饭</html>


吃饭


感觉还是spring好,一点一滴的比较贴心。



转载于:https://my.oschina.net/messi31/blog/535329

你可能感兴趣的:(sql特殊字符转义处理,防止注入)