聊聊SQL注入
SQL注入问题
概述:
- 首先SQL注入是一个非常危险的操作,很可能被一些不怀好意的人钻空导致我们系统出现异常等状况,比如数据库遭到破坏或被入侵。
原因:使用JDBC的Statement语句添加SQL语句
由于我们的JDBC在对数据库进行操作时,需要客户端传入一些参数。我们在日常中的处理是将字符串参数作为SQL语句进行拼接,但是加入客户端传入SQL语句关键字恶意篡改SQL语句就会改变服务端SQL语义发生系统异常。严重时就会导致系统和数据库破坏,这时的攻击方式就叫SQL注入了。
实例:模拟登录请求传入用户id和密码参数,使用字符串拼接导致的SQL注入。
拼接SQL语句,就会出现SQL注入的安全问题,拼接代码如下:
String sql = "select * from user where username='" + uid + "' and password='" + passwd + "'";
若此时传入参数如下:永真式 或 封号结束注释后面条件验证(只能说人的脑洞真大哈哈)
params.put("uid", "malongfei");
params.put("passwd", "111' or '1' = '1");
// 或者
params.put("uid", "malongfei'; -- ")
// 或者
params.put("uid", "malongfei'; # ")
此时JDBC还没意识到安全问题,依旧将以上参数拼接到我们的SQL原语中,如下:
select * from user where uid = 'malongfei' and passwd = '111' or '1' = '1';
select * from user where uid = 'malongfei'; -- ' and passwd = '111' or '1' = '1';
select * from user where uid = 'malongfei'; # ' and passwd = '111' or '1' = '1';
预防SQL注入:使用PreparedStatement代替Statement可以有效防止SQL注入。
- PreparedStatement利用预编译的机制将sql语句的主干和参数分别传输给数据库服务器,这样即使参数中携带数据库关键字,也不能作为SQL中真正的关键字而起作用。
// 后端登录验证密码接口的SQL语句
select * from user where uid = ? and passwd = ?;
- 设置黑名单也可提前预防,单纯针对于用户输入中含有SQL关键字的拦截方法,比如在注册账号时,用户名和密码中不能含有SQL语句关键字;
- 或者说在进行SQL拼接时加入逻辑处理,对传入参数含有SQL关键字的进行报输入异常。
PreparedStatement 与 Statment 区别:
- 语法不同:PreparedStatement 使用预编译的sql,而 Statment 使用静态的sql
- 效率不同: PreparedStatement 具有 sql缓存区,效率比 Statment 高
- 安全性不同:PreparedStatement 可以有效防止sql注入,而 Statment 不能
Mybatis对SQL注入的预防处理
出现SQL注入问题的原因和上面一样,都是由于拼接SQL导致的,只不过方式不同。
- Mybatis接收参数处理有两种语法:
#{}
和${}
,#
使用预编译,$
使用拼接SQL方式。 - 这里需要注意的是:使用#运算符,Mybatis会将传入的参数当成一个字符串,在进行变量替换时会加上引号!
- Mybatis接收参数处理有两种语法:
mybatis 出现SQL注入实例:
模糊查询时,如下实例:
采用
#{}
的话程序会报异常。最后替换成like "'name'"
select * from users where name like '%#{name}%'
常人看了既然#{}报错那么我用${},正中SQL注入的下怀,这个时候倘若我们的服务端 Java 代码没有对传入参数进行拦截处理,SQL注入条件满足!
select * from users where name like '%${name}%'
正确SQL写法,需要使用 concat函数 来进行连接参数(concat为mysql函数,连接参数产生字符串)
select * from users where name like concat('%',#{name}, '%')
补充:
in
之后的多个参数在mybatis中也不能采用#{}
或者${}
,需要使用动态SQL语法中foreach
循环遍历select * from users where id in
<foreach collection="ids" item="item" open="("separatosr="," close=")">
#{item}
</foreach>
order by
之后也不能使用#{}
,他也会将字段改为字符串形式,加上引号后就不能正常排序,所以我们需要考虑${}
的方式,但是在后台代码中一定要进行数据参数的校验等手段,防止SQL注入.
最新文章
- 学习Redis你必须了解的数据结构——HashMap实现
- javaScript中定义类或对象的五种方式
- 共享内存 share pool (2):BUCKET /FREE LISTS /RESERVED FREE LISTS /UNPINNED RECREATABLE CHUNKS (lru first)
- hdu2041java
- PHP图片文件上传类型限制扩展名限制大小限制与自动检测目录创建。
- SQL之单行函数
- python正文(两)
- 在点击div中的p时,如何阻止事件冒泡?
- 关于mysql增删改查的基本操作
- Python 配置 selenium 模拟浏览器环境,带下载链接
- MySql Undo Redo
- Unity3D中Isometric Tilemap功能实践
- 高级组件——工具栏JToolBar
- 如何使用 Deepfakes 换脸
- SQL SERVER占用CPU过高优化
- [BZOJ4722]由乃[鸽巢原理+bitset+倍增]
- 注册IIS的批处理
- webstorm下搭建编译less环境 以及设置压缩css
- 《R语言实战》读书笔记--第五章 高级数据管理
- Java学习笔记4---打包成双击可运行的jar文件
热门文章
- 安装linux下一些常用软件
- 多线程与高并发(二)—— Synchronized 加锁解锁流程
- Hippo4J v1.3.1 发布,增加 Netty 监控上报、SpringCloud Hystrix 线程池监控等特性
- JavaScript进阶内容——jQuery
- 序列化和返序列化的概述和对象的序列化流ObjectOutputStream
- python 常用的魔法函数
- 一寸宕机一寸血,十万容器十万兵|Win10/Mac系统下基于Kubernetes(k8s)搭建Gunicorn+Flask高可用Web集群
- vue之请求axios
- Nodemon 如何实时监听 TypeScript 项目下的文件并热部署?
- Dart 异步编程(三):详细认识