行业资讯 2025年08月6日
0 收藏 0 点赞 266 浏览 2191 个字
摘要 :

文章目录 案例 解决方法 1)test表 2)TestEntity 3)入参 4)Mapper.xml里的SQL 5)实现限制方法  6)使用校验 总结 学过mybatis的同学应该都知道,为了避免SQL注入……




  • 案例
  • 解决方法
    • 1)test表
    • 2)TestEntity
    • 3)入参
    • 4)Mapper.xml里的SQL
    • 5)实现限制方法
    •  6)使用校验
  • 总结

学过mybatis的同学应该都知道,为了避免SQL注入,mybatis语句中要尽量使用 #{xxx}来避免SQL注入,而尽量不要使用${xxx},原因也很简单,就是因为${xxx}这样格式的参数会直接参与SQL 编译,该参数内容会直接影响SQL语句结构,从而无法避免注入攻击,而#{xxx} 参数只会作为字符串参数进行拼接,再执行编译,不会影响SQL原本结构。

既然如此,那为何还要有${xxx} 这种简单的占位符呢?原因在于有一种特殊情况,当涉及到动态表名和列名时,只能使用${xxx}这样的参数格式。为了SQL防止注入,我们只能通过手工处理入参来进行防止注入操作。

案例

比较常见的案例就是根据不同的字段进行排序,排序方式也可以动态实现升序和降序。

解决方法

以下是一个相关实现mybatis使用${}避免SQL注入的案例方法。

核心思路:针对查询入参的动态字段,将其取值限制在SQL表对应的Entity的字段类,如果动态字段不在Entity内就说明是非法入参

1)test表

这里假设我们test表有param1,param2,param3这3个字段。

2)TestEntity

该表对应的TestEntity自然也会包含param1,param2,param3这3个属性。

3)入参

比如现在根据动态字段进行排序,查询入参如下:

@Data
public class QueryRequest implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 查询字段1
     */
    private String param1;

    /**
     * 排序字段
     */
    private String orderField;

   /**
     * 排序类型
     */
    private String orderType;
}

4)Mapper.xml里的SQL

我们Mapper.xml查询SQL如下:

select * from test 
<where> 
// 这里省略...
</where>
order by ${orderField} ${orderType} 

我们发现这里使用了${orderField}/${orderType} 存在SQL注入风险,如果sortField传一个注入语句那就危险了,因此我们在Service或者Controller层对orderField/orderType的取值要进行限制为param1或param2或param3或asc或desc,即TestEntity中的字段以及排序类型。

5)实现限制方法

我们利用反射写一个通用的限制方法如下(这里还允许升降序的取值限制):

public class DynamicOrderUtils {
    private static final List<String> ORDER_TYPES = Arrays.asList(\"descend\", \"ascend\", \"desc\", \"asc\");

    /**
     * 获取对象可以排序的属性值列表
     *
     * @param object
     * @return
     */
    private static Set<String> getTableFields(Class<?> object) {
        //获取filed数组
        Set<String> resultList = new HashSet<>();
        try {
            Field[] fields = object.getDeclaredFields();
            for (Field field : fields) {
                resultList.add(field.getName());
            }
            return resultList;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultList;
    }

    /**
     * 判断动态order是否是合理
     *
     * @param object
     * @return
     */
    public static boolean isRight(String orderColumn, String orderType, Class<?> object) {
        //先获取所有可用排序属性
        Set<String> columnSet = getTableFields(object);
        return (StringUtils.isBlank(orderColumn) || columnSet.contains(orderColumn)) && (StringUtils.isBlank(orderType) || ORDER_TYPES
            .contains(orderType.toLowerCase()));
    }

}

 6)使用校验

最后我们在Service或者Controller层对orderField/orderType的取值要进行限制,只需调用如下方法:

boolean right = DynamicOrderUtils.isRight(queryRequest.getOrderField(), queryRequest.getOrderType(), TestEntity.class);

如果返回true,说明满足条件,否则你可以抛出异常提示。

总结

以上就是mybatis使用${}如何避免SQL注入的全部内容,目前还没有更好的解决方案,如果你有更好的方案,欢迎留言!

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/9447.html

管理员

上一篇: Swagger简介
相关推荐
2025-08-06

文章目录 一、Reader 接口概述 1.1 什么是 Reader 接口? 1.2 Reader 与 InputStream 的区别 1.3 …

988
2025-08-06

文章目录 一、事件溯源 (一)核心概念 (二)Kafka与Golang的优势 (三)完整代码实现 二、命令…

465
2025-08-06

文章目录 一、证明GC期间执行native函数的线程仍在运行 二、native线程操作Java对象的影响及处理方…

348
2025-08-06

文章目录 一、事务基础概念 二、MyBatis事务管理机制 (一)JDBC原生事务管理(JdbcTransaction)…

456
2025-08-06

文章目录 一、SnowFlake算法核心原理 二、SnowFlake算法工作流程详解 三、SnowFlake算法的Java代码…

517
2025-08-06

文章目录 一、本地Jar包的加载操作 二、本地Class的加载方法 三、远程Jar包的加载方式 你知道Groo…

832
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号