一、Mybatis动态参数说明
| 参数符号 | 编译 | 安全 | 值 |
| #{} | 预编译 | 安全 | ?替换,处理后的值,字符类型都带双引号 |
| ${} | 未预编译 | 不安全,存在SQL注入问题 | 页面传什么值就是什么值 |
二、order by 动态参数值说明
1、order by后面使用#{} 是无效的,只能使用${}。如果使用${}是会引起SQL注入的。
三、动态参数校验防止SQL注入
1、查询BO对象定义好排序参数
@ApiModelProperty(value = "排序字段") private String column; @ApiModelProperty(value = "排序方式") private String order;
2、自定义校验参数是否非法方法,如果排序字段任一为空,则不排序,排序方式只能是desc或者asc,否则校验排序字段是否合法。
/**
* 排序参数是否非法
*
* @param column 字段
* @param order 类对象
* @param obj 类对象
* @return true:不排序或不存在非法
*/
public static String isParamIllegal(String column, String order, Object obj) {
if (StringUtils.isEmpty(column) || StringUtils.isEmpty(order)) {
return "true";
} else {
if ("desc".equals(order) || "asc".equals(order)) {
// 如果不等于则返回false
} else {
return "order参数非法,请检查!";
}
}
// 判断排序字段是否存在对应实体中
if (isExistField(column, obj)) {
return "true";
} else {
return "column参数非法,请检查!";
}
}3、通过将实体对象转为json对象,判断是否属于定义好的参数。
/**
* 判断你一个类是否存在某个属性(字段)
*
* @param field 字段
* @param obj 类对象
* @return true:存在,false:不存在, null:参数不合法
*/
public static Boolean isExistField(String field, Object obj) {
if (obj == null || StringUtils.isEmpty(field)) {
return null;
}
Object o = JSON.toJSON(obj);
JSONObject jsonObj = new JSONObject();
if (o instanceof JSONObject) {
jsonObj = (JSONObject) o;
}
return jsonObj.containsKey(field);
}4、将驼峰字段转换为数据库下划线字段
/**
* 将驼峰命名转化成下划线
*
* @param para
* @return
*/
public static String camelToUnderline(String para) {
if (para.length() < 3) {
return para.toLowerCase();
}
StringBuilder sb = new StringBuilder(para);
int temp = 0;//定位
//从第三个字符开始 避免命名不规范
for (int i = 2; i < para.length(); i++) {
if (Character.isUpperCase(para.charAt(i))) {
sb.insert(i + temp, "_");
temp += 1;
}
}
return sb.toString().toLowerCase();
}5、通过校验后再传入查询对象
TestObject testObject = new TestObject ();
String msg = CommonUtils.isParamIllegal(testObjectQueryBO.getColumn(), testObjectQueryBO.getOrder(), testObject );
if (!"true".equals(msg)) {
return Result.OK(msg);
} else {
if (StringUtils.isNotBlank(testObjectQueryBO.getColumn())) {
testObjectQueryBO.setColumn(oConvertUtils.camelToUnderline(testObjectQueryBO.getColumn()));
}
}6、xml代码,如果传入字段不是创建时间,则先按排序字段排序,再按创建时间倒叙排序。
<choose>
<when test="testObjectQueryBO.column!=null and testObjectQueryBO.column=='create_time' and testObjectQueryBO.order!=null and testObjectQueryBO.order!=''">
ORDER BY ${testObjectQueryBO.column} ${testObjectQueryBO.order}
</when>
<otherwise>
<if test="testObjectQueryBO.column!=null and testObjectQueryBO.column!='' and testObjectQueryBO.order!=null and testObjectQueryBO.order!=''">
ORDER BY ${testObjectQueryBO.column} ${testObjectQueryBO.order}, create_time DESC
</if>
</otherwise>
</choose>四、总结
1、动态排序的实现方式有很多,我这种只是其一。我的方法是之前过滤防止传入非法参数,虽然实现方式复杂了一点,但是至少安全。
2、有些人的实现方式是通过判断排序字段是否包含delete、;、等标识判断是否非法。如下:
<if test='sort !=null and sort !="" and !sort.contains(";")'>
order by ${sort}
</if>
3、条条大路通罗马,适用于自己项目的才是最好的防注入动态排序。
版权声明:本文为wode3157695297原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。