您的需求已经提交,我们将在48小时内联系您
全国服务热线:400-1000-221
确定
免费享受企业级云安全服务
获取手机验证码
{{message}}
免费试用

mybatis如何防止sql注入?mybatis 防止sql注入的方法介绍

作者:
发布时间:2020-08-27

  在一些安全性要求很高的应用中(比如银行软件),经常使用将SQL语句全部替换为存储过程这样的方式,来防止SQL注入。这里就跟大家讲解一下mybatis如何防止sql注入mybatis 防止sql注入的方法

mybatis如何防止sql注入

mybatis如何防止sql注入

 

  mybatis如何防止sql注入?MyBatis是如何做到SQL预编译的呢?其实在框架底层,是JDBC中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的SQL语句。这种“准备好”的方式不仅能提高安全性,而且在多次执行同一个SQL时,能够提高效率。原因是SQL已编译好,再次执行时无需再编译,编译完成后的SQL:SELECT author,content FROM blog WHERE id = ?,传进来的id参数是一个整体,比如id='or 1=1',就查找不到。

  在MyBatis中,“${xxx}”这样格式的参数会直接参与SQL编译,从而不能避免注入攻击。但涉及到动态表名和列名(比如order by根据哪一列排序)时,只能使用“${xxx}”这样的参数格式。所以,这样的参数需要我们在代码中手工进行处理来防止注入。

  【结论】在编写MyBatis的映射语句时,尽量采用“#{xxx}”这样的格式。若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止SQL注入攻击。

mybatis 防止sql注入的方法

  SQL注入大多数也会比较清楚,就是SQL参数对应的字段值时插入混合SQL,如 ** username = or 1= 1** 这种,如果有更恶劣的,带上drop database 这种都是有可能的,所以一般SQL都会进行一定防注入处理,MyBatis其实用法大都清楚,就是**#{paras}和${paras}**两种用法,以前我就是会用,但是具体原理咱也没看过,在一次面试中,被别人问到过具体用法,注入原理,处理原理等等,当时就是根据自己的印象去回答了,但是对于MyBatis与数据库具体处理SQL注入却不是很熟悉的,这一节就来详细讲解下,记录一下。

  #1. #{paras}与${paras}用法

  对于**#{paras}和KaTeX parse error: Expected 'EOF', got '#' at position 23: …**写两个用法吧,一个根据**#̲{paras}**来查询,一种…{paras}**来查询,如下:

  @ResultMap("BaseResultMap")@Select("select * from user where username = #{username}")User getUserByParas1(@Param("username") String username);@ResultMap("BaseResultMap")@Select("select * from user where username = ${username}")List getUserByParas2(@Param("username") String username);

  调用这两个方法的程序为:

  User user = userMapper.getUserByParas1("xiaxuan");List users = userMapper.getUserByParas2(" 1 or 1 = 1");System.out.println(user);System.out.println(users);

  运行结果为:

  

mybatis 防止sql注入的方法

 

  运行结果和想象中差不多,在conf.xml中添加打印sql的配置.

  再运行一次看看,如下图:

  

mybatis 防止sql注入的方法

 

  第一个sql是进行了占位符处理,第二个是直接拼出了sql语句。

  上述就是演示#{paras}调用和和sql注入的过程,下面开始讲两者在实现过程中的原理。

  2. 初始化源码分析

  首先看看这两个方法是怎么加载的,这还是要回到注解方法的解析中,在前文中我们知在解析注解时,会将当前sql包装成SqlSource对象,然后在查询时使用,代码如下:

  void parseStatement(Method method) { Class parameterTypeClass = getParameterType(method); LanguageDriver languageDriver = getLanguageDriver(method); SqlSource sqlSource = getSqlSourceFromAnnotations(method, parameterTypeClass, languageDriver); .....}

  我们进getSqlSourceFromAnnotations方法中看看。

  private SqlSource getSqlSourceFromAnnotations(Method method, Class parameterType, LanguageDriver languageDriver) { try { Class sqlAnnotationType = getSqlAnnotationType(method); Class sqlProviderAnnotationType = getSqlProviderAnnotationType(method); if (sqlAnnotationType != null) { if (sqlProviderAnnotationType != null) { throw new BindingException("You cannot supply both a static SQL and SqlProvider to method named " + method.getName()); } Annotation sqlAnnotation = method.getAnnotation(sqlAnnotationType); final String[] strings = (String[]) sqlAnnotation.getClass().getMethod("value").invoke(sqlAnnotation); return buildSqlSourceFromStrings(strings, parameterType, languageDriver); } else if (sqlProviderAnnotationType != null) { Annotation sqlProviderAnnotation = method.getAnnotation(sqlProviderAnnotationType); return new ProviderSqlSource(assistant.getConfiguration(), sqlProviderAnnotation, type, method); } return null; } catch (Exception e) { throw new BuilderException("Could not find value method on SQL annotation. Cause: " + e, e); } }

  此处我们只分析带有@Select注解的方法,所有就是进入if条件中进行处理,这里再进入buildSqlSourceFromStrings方法。

  private SqlSource buildSqlSourceFromStrings(String[] strings, Class parameterTypeClass, LanguageDriver languageDriver) { final StringBuilder sql = new StringBuilder(); for (String fragment : strings) { sql.append(fragment); sql.append(" "); } return languageDriver.createSqlSource(configuration, sql.toString().trim(), parameterTypeClass); }

  最后通过languageDriver返回SqlSource,进入createSqlSource方法中。

  @Override public SqlSource createSqlSource(Configuration configuration, String script, Class parameterType) { SqlSource source = super.createSqlSource(configuration, script, parameterType); checkIsNotDynamic(source); return source; }@Override public SqlSource createSqlSource(Configuration configuration, String script, Class parameterType) { // issue #3 if (script.startsWith("

  

mybatis如何防止sql注入?mybatis

 

  关于mybatis如何防止sql注入以及mybatis 防止sql注入的方法就为大家介绍到这里,MyBatis 是一种持久层框架,介于 JDBC 和 Hibernate 之间。通过 MyBatis 减少了手写 SQL 语句的痛苦,使用者可以灵活使用 SQL 语句,支持高级映射。

标签: