mybatis中的like查询,$取值时防sql注入和通配符注入,#取值时防通配符注入

来源:互联网 发布:vba 连接mysql 编辑:程序博客网 时间:2024/06/11 18:37

在mybatis中用like查询时,如果用户输入的值有"_"和“%”,则会出现这种情况:

用户本来只是想查询“abcd_”,查询结果中却有"abcd_"、"abcde"、"abcdf"等等;用户要查询"30%"(注:百分之三十)时也会出现问题。

测试后发现无论你是用#{xxxx }还是用${xxxx }取值都会存在这些问题,而且用${xxxx }取值时还存在sql注入的问题。

为了解决这些问题,我在后台对用户传入的值进行了处理,代码如下:

import org.apache.commons.lang3.StringUtils;/** * mybatis中like查询时,需用该方法处理字符,防止sql注入<br> * sql server 2005测试有效 *  * @date    2013年12月9日 下午4:08:54 * @version 1.0 * @author  luoy */public class SqlUtil {private static final String H = "#";private static final String S = "$";/** * mapper.xml中的取值方式为#{}时 * @param str like的查询条件 * @return */public static String likeEscapeH(String str) {return likeEscapeZ(str, H, true, true);}/** * mapper.xml中的取值方式为${}时 * @param str like的查询条件 * @return */public static String likeEscapeS(String str) {return likeEscapeZ(str, S, true, true);}/** * @param str   like的查询条件 * @param type  mapper.xml中的取值方式,只能“#”或“$” * @param start 字符串前部是否拼接“%” * @param end   字符串尾部是否拼接“%” * @return */public static String likeEscapeZ(String str, String type, boolean start, boolean end) {if (StringUtils.isBlank(str)) {return null;}StringBuffer buffer = new StringBuffer();// 拼接顺序不能改变if (S.equals(type)) {buffer.append(" '");}if (start) {buffer.append("%");}int len = str.length();//注意:"]"不能处理for (int i = 0; i < len; i++) {char c = str.charAt(i);switch (c) {case '\'':if (S.equals(type)) {buffer.append("''");// 单引号替换成两个单引号} else {buffer.append(c);}break;case '[':buffer.append("[[]");break;case '_':buffer.append("[_]");break;case '%':buffer.append("[%]");break;case '^':buffer.append("[^]");break;case '!':buffer.append("[!]");break;default:buffer.append(c);}}if (end) {buffer.append("%");}if (S.equals(type)) {buffer.append("' ");}return buffer.toString();}public static void main(String[] args) {String str = "aaaa]p'100%_a[[][][]][[][]]df[]dfaf]";System.out.println("result#: " + likeEscapeH(str));System.out.println("result$: " + likeEscapeS(str));}}


看了代码的人应该很容易就明白了。这里的三个方法分别对应多种可能的情况,第一个是#号取值,参数前后都加百分号;第二个方法是$取值,参数前后都加百分号;第三个方法是参数可配,而且考虑到了,有时候不需要前后都加百分号的情况。

xml中的写法:

1,

<if test="xxx != null" >

select * from tabale_name a where  a.xxx like ${xxx }

</if>

2,

<if test="xxx != null" >

select * from tabale_name a where  a.xxx like #{xxx }

</if>


添加oracle适用类

import org.apache.commons.lang3.StringUtils;/** * oracle 适用<br/> * mybatis中like查询用$取值时,需用该方法处理字符,防止sql注入<br/> *  * @date 2016年01月20日 * @author 罗勇 */public final class SqlUtil {    /**     * mapper.xml中的取值方式为${}时     *      * @param str     *            like的查询条件     * @return     */    public static String likeEscape(String str) {        return likeEscape(str, true, true);    }    /**     * @param str     *            like的查询条件     * @param start     *            字符串前部是否拼接“%”     * @param end     *            字符串尾部是否拼接“%”     * @return     */    public static String likeEscape(String str, boolean start, boolean end) {        if (StringUtils.isBlank(str)) {            return null;        }        StringBuilder buf = new StringBuilder();        // 拼接顺序不能改变        buf.append(" '");        if (start) {            buf.append("%");        }        boolean flag = false;        int len = str.length();        for (int i = 0; i < len; i++) {            char c = str.charAt(i);            switch (c) {            case '\'':                buf.append("''");// 单引号替换成两个单引号                break;            case '_':                buf.append("\\_");                flag = true;                break;            case '%':                buf.append("\\%");                flag = true;                break;            default:                buf.append(c);            }        }        if (end) {            buf.append("%");        }        buf.append("' ");        if (flag) {            buf.append("escape '\\' ");        }        return buf.toString();    }    private SqlUtil() {    }    public static void main(String[] args) {        String str = "aaaa]p'100%_a[[][][]][[][]]df[]dfaf]!bbb^";        System.out.println("result$: " + likeEscape(str));    }}


0 0
原创粉丝点击