zoukankan      html  css  js  c++  java
  • MyBatis如何防止SQL注入

    SQL注入起因

    SQL注入是一种常见的攻击方式,攻击者或者误操作者通过表单信息或者URL输入一些异常的参数,传入服务端进行SQL处理,可能会出现这样的情况delete from app_poi where poi_id = (输入参数):

    输入参数:10 or 1 = 1

    SQL拼接:delete from app_poi where poi_id = (10 or 1 = 1)

    执行结果:app_poi中的所有数据都会被delete

    这种问题出现的原因可能是攻击者故意为之,也可能是误操作,那么服务端该如何处理,避免这样的问题出现呢?

    MyBatis

    MyBatis是一种半自动化持久化框架,所有SQL操作都需要我们通过配置文件或者注解的方式手动编辑,它提供了一种类函数的功能,用户提供输入,MyBatis根据输入类型和输入参数进行验证,如果参数没有问题,那么MyBatis就针对合法的输入提供输出,即

    用户输入参数+用户输入类型 ---> MyBatis检测 ---> 返回输出

    接下来通过配置文件和注解两种方式来进行说明

    • 配置文件:
    <delete id="deletePoiById" parameterType="java.lang.Integer">
        DELETE
        FROM app_poi
        where poi_id = #{poiId}
    </delete>
    • 基于注解
    @delete("delete from app_poi where poi_id = #{poiId}")
    public void deletePoiById(@Param("poiId") Integer poiId);

    MyBatis对用户输入的数据会检测其类型是否和parameterType标识的类型一致,如果一致,则进行后续拼接处理,否则抛出异常,SQL就不会执行

    对于10 or 1 = 1这种输入,和java.lang.Integer类型不同,就会abort并抛出异常

    原理

    MyBatis使用#{}防止SQL注入,其实使用的是PreparedStatement,PreparedStatement会对执行SQL进行预编译,这个过程是发生在数据库服务端,也就是说,对于PreparedStatement的SQL需要两次网络请求,首次是获取PreparedStatement,第二次才是发起SQL执行;

    PreparedStatement会对SQL中输入的参数进行检测,并在SQL都是用问号来设置占位符,即只允许传入一个参数,像(10 or 1 = 1)这种明显不会被占位符所接受

    String类型SQL注入

    对于数字类型参数#{}可以很好的解决SQL注入,其原因不难理解,那么对于string类型的呢?Mybatis只是使用了一个占位符并不能解决该问题

    <delete id="deletePoiById" parameterType="java.lang.String">
        DELETE
        FROM app_poi
        where content = #{content}
    </delete>

    如果content的内容是“美食 or 1 = 1”,那么数据将会被全部清除

    解决该问题,还是结合传统方式,使用正则表达式匹配,总结常见的需要摒弃的string,替换为空即可,例如string包含

    and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|; |or|-|+|,等

    哔哔叭哔哄
  • 相关阅读:
    CentOS下添加sudo用户
    CentOS查看你是否有USB 3.0端口
    CentOS查看操作系统信息(重要)
    JStack分析cpu消耗过高问题
    Java内存管理和垃圾回收
    kafka学习之-深入研究原理
    kafka学习之-文件存储机制
    kafka学习之-配置详解
    Hbase学习之javaApI封装
    linux中top命令
  • 原文地址:https://www.cnblogs.com/he-px/p/7592028.html
Copyright © 2011-2022 走看看