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

在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));
    }
}


  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值