Mybatis是如何实现SQL防注入的
Mybatis这个框架在日常开发中用的很多,比如面试中经常有一个问题:$
和#
的区别,它们的区别是使用#
可以防止SQL注入,今天就来看一下它是如何实现SQL注入的。
什么是SQL注入
在讨论怎么实现之前,首先了解一下什么是SQL注入,我们有一个简单的查询操作:根据id查询一个用户信息。它的sql语句应该是这样:select * from user where id =
。我们根据传入条件填入id进行查询。
如果正常操作,传入一个正常的id,比如说2,那么这条语句变成select * from user where id =2
。这条语句是可以正常运行并且符合我们预期的。
但是如果传入的参数变成 '' or 1=1
,这时这条语句变成select * from user where id = '' or 1=1
。让我们想一下这条语句的执行结果会是怎么?它会将我们用户表中所有的数据查询出来,显然这是一个大的错误。这就是SQL注入。
Mybatis如何防止SQL注入
在开头讲过,可以使用#
来防止SQL注入,它的写法如下:
<select id="safeSelect" resultMap="testUser">
SELECT * FROM user where id = #{id}
</select>
在mybatis中查询还有一个写法是使用$
,它的写法如下:
<select id="unsafeSelect" resultMap="testUser">
select * from user where id = ${id}
</select>
当我们在外部对这两个方法继续调用时,发现如果传入安全的参数时,两者结果并无不同,如果传入不安全的参数时,第一种使用#
的方法查询不到结果(select * from user where id = '' or 1=1
),但这个参数在第二种也就是$
下会得到全部的结果。
并且如果我们将sql进行打印,会发现添加#
时,向数据库执行的sql为:select * from user where id = ' \'\' or 1=1 '
,它会在我们的参数外再加一层引号,在使用$
时,它的执行sql是select * from user where id = '' or 1=1
。
弃用$
可以吗
我们使用#
也能完成$
的作用,并且使用$
还有危险,那么我们以后不使用$
不就行了吗。
并不是,它只是在我们这种场景下会有问题,但是在有一些动态查询的场景中还是有不可代替的作用的,比如,动态修改表名select * from ${table} where id = #{id}
。我们就可以在返回信息一致的情况下进行动态的更改查询的表,这也是mybatis动态强大的地方。
如何实现SQL注入的,不用Mybatis怎么实现
其实Mybatis也是通过jdbc来进行数据库连接的,如果我们看一下jdbc的使用,就可以得到这个原因。
#
使用了PreparedStatement
来进行预处理,然后通过set的方式对占位符进行设置,而$
则是通过Statement
直接进行查询,当有参数时直接拼接进行查询。
所以说我们可以使用jdbc来实现SQL注入。
看一下这两个的代码:
public static void statement(Connection connection) {
System.out.println("statement-----");
String selectSql = "select * from user";
// 相当于mybatis中使用$,拿到参数后直接拼接
String unsafeSql = "select * from user where id = '' or 1=1;";
Statement statement = null;
try {
statement = connection.createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
try {
ResultSet resultSet = statement.executeQuery(selectSql);
print(resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
System.out.println("---****---");
try {
ResultSet resultSet = statement.executeQuery(unsafeSql);
print(resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void preparedStatement(Connection connection) {
System.out.println("preparedStatement-----");
String selectSql = "select * from user;";
//相当于mybatis中的#,先对要执行的sql进行预处理,设置占位符,然后设置参数
String safeSql = "select * from user where id =?;";
PreparedStatement preparedStatement = null;
try {
preparedStatement = connection.prepareStatement(selectSql);
ResultSet resultSet = preparedStatement.executeQuery();
print(resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
System.out.println("---****---");
try {
preparedStatement = connection.prepareStatement(safeSql);
preparedStatement.setString(1," '' or 1 = 1 ");
ResultSet resultSet = preparedStatement.executeQuery();
print(resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void print(ResultSet resultSet) throws SQLException {
while (resultSet.next()) {
System.out.print(resultSet.getString(1) + ", ");
System.out.print(resultSet.getString("name") + ", ");
System.out.println(resultSet.getString(3));
}
}
总结
- Mybatis中使用
#
可以防止SQL注入,$
并不能防止SQL注入 - Mybatis实现SQL注入的原理是调用了jdbc中的
PreparedStatement
来进行预处理。
本文由博客一文多发平台 OpenWrite 发布!
博主邮箱:liunaijie1996@163.com,有问题可以邮箱交流。
Mybatis是如何实现SQL防注入的的更多相关文章
- SQL防注入程序 v1.0
/// ***************C#版SQL防注入程序 v1.0************ /// *使用方法: /// 一.整站防注入(推荐) /// 在Global.asax.cs中查找App ...
- PHP之SQL防注入代码集合(建站常用)
SQL防注入代码一 <?php if (!function_exists (quote)) { function quote($var) { if (strlen($var)) { $var=! ...
- sql 防注入 维基百科
http://zh.wikipedia.org/wiki/SQL%E8%B3%87%E6%96%99%E9%9A%B1%E7%A2%BC%E6%94%BB%E6%93%8A SQL攻击(SQL inj ...
- 特殊字符的过滤方法,防sql防注入代码的过滤方法
特殊字符的过滤方法 function strFilter($str){ //特殊字符的过滤方法 $str = str_replace('`', '', $str); $str = str_replac ...
- SQL防注入程序
1.在Global.asax.cs中写入: protected void Application_BeginRequest(Object sender,EventArgs e){ SqlIn ...
- PHP SQL防注入
过年前后在做一个抽奖的东西,需要用户填写中奖信息,为了防止非法用户对数据库进行入侵神马的,于是写下基本的防注入语句,需要用的可以自己封装成一个function. $str = str_replace( ...
- 360提供的SQL防注入
<?php class sqlsafe { private $getfilter = "'|(and|or)\\b.+?(>|<|=|in|like)|\\/\\*.+?\ ...
- .net sql 防注入 httpmodule
1 新建一个类,实现IHttpModule接口 using System; using System.Collections.Generic; using System.Linq; using Sys ...
- PHP之SQL防注入代码(360提供)
<?php class sqlsafe { private $getfilter = "'|(and|or)\\b.+?(>|<|=|in|like)|\\/\\*.+?\ ...
随机推荐
- 【转载】字符编码笔记:ASCII,Unicode和UTF-8
字符编码笔记:ASCII,Unicode和UTF-8 作者: 阮一峰 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直 ...
- Bert系列(二)——源码解读之模型主体
本篇文章主要是解读模型主体代码modeling.py.在阅读这篇文章之前希望读者们对bert的相关理论有一定的了解,尤其是transformer的结构原理,网上的资料很多,本文内容对原理部分就不做过多 ...
- Facebook 发布深度学习工具包 PyTorch Hub,让论文复现变得更容易
近日,PyTorch 社区发布了一个深度学习工具包 PyTorchHub, 帮助机器学习工作者更快实现重要论文的复现工作.PyTorchHub 由一个预训练模型仓库组成,专门用于提高研究工作的复现性以 ...
- OpenStack组件系列☞glance搭建
第一步:glance关于数据库的操作 mysql -u root -p #登入数据库 CREATE DATABASE glance; #新建库keystone GRANT ALL PRIVILEGES ...
- [C#] 用ServiceStack读写redis的性能问题
ServiceStack.Redis有个方法叫 AddRangeToList,这个方法是有性能问题的.这个方法的实现代码如下: public void AddRangeToList(string li ...
- Element-ui学习笔记2
1.Button按钮 <el-button> type属性可以修改按钮主题 type='text'时为文字按钮 plain,round,circle可以修改按钮样式,plain为朴素按钮, ...
- Echarts Map地图下钻至县级
**准备工作:**1.首先使用vue-cli的脚手架生成vue项目. 2.然后使用npm安装echartsnpm install echarts -S 3.安装完后再mian.js中挂载到vue的实例 ...
- Python--day71--分页功能
分页功能代码: from django.shortcuts import render # Create your views here. from app01 import models def b ...
- H3C 高级ACL部署位置示例
- 安装 NodeJ Koa2、3 + 独立插件 cli脚手架 npm cnpm Vue
安装 NodeJ npm cnpm Koa2.3 + 独立插件 cli脚手架 Vue 安装 在 这里写过了 这两个分开了写 Nodej:下载 node.js 安装 10.0版 ...