用java PreparedStatement就不用担心sql注入了吗?
先感慨下,好久没写博客了,一是工作太忙,二是身体不太给力,好在终于查清病因了,趁着今天闲下来,迫不及待与读者交流,最后忠告一句:身体是活着的本钱!
言归正传,对java有了解的同学基本上都体验过JDBC,基本都了解PreparedStatement,PreparedStatement相比Statement基本解决了SQL注入问题,而且效率也有一定提升。
关于PreparedStatement和Statement其他细节我们不讨论,只关心注入问题。无论读者是老鸟还是菜鸟,都需要问一下自己,PreparedStatement真的百分百防注入吗?
接下来我们研究一下PreparedStatement如何防止注入,本文以MySQL数据库为例。
为了避免篇幅过长,我这里只贴代码片段,希望读者能有一定的基础。
String sql = "select * from goods where min_name = ?"; // 含有参数
PreparedStatement st = conn.prepareStatement(sql);
st.setString(1, "儿童"); // 参数赋值
System.out.println(st.toString()); //com.mysql.jdbc.JDBC4PreparedStatement@d704f0: select * from goods where min_name = '儿童'
这段代码属于JDBC常识了,就是简单的根据参数查询,看不出什么端倪,但假如有人使坏,想注入一下呢?
String sql = "select * from goods where min_name = ?"; // 含有参数
PreparedStatement st = conn.prepareStatement(sql);
st.setString(1, "儿童'"); // 参数赋值
System.out.println(st.toString()); //com.mysql.jdbc.JDBC4PreparedStatement@d704f0: select * from goods where min_name = '儿童\''
简单的在参数后边加一个单引号,就可以快速判断是否可以进行SQL注入,这个百试百灵,如果有漏洞的话,一般会报错。
之所以PreparedStatement能防止注入,是因为它把单引号转义了,变成了\',这样一来,就无法截断SQL语句,进而无法拼接SQL语句,基本上没有办法注入了。
所以,如果不用PreparedStatement,又想防止注入,最简单粗暴的办法就是过滤单引号,过滤之后,单纯从SQL的角度,无法进行任何注入。
其实,刚刚我们提到的是String参数类型的注入,大多数注入,还是发生在数值类型上,幸运的是PreparedStatement为我们提供了st.setInt(1, 999);这种数值参数赋值API,基本就避免了注入,因为如果用户输入的不是数值类型,类型转换的时候就报错了。
好,现在读者已经了解PreparedStatement会对参数做转义,接下来再看个例子。
String sql = "select * from goods where min_name = ?"; // 含有参数
PreparedStatement st = conn.prepareStatement(sql);
st.setString(1, "儿童%"); // 参数赋值
System.out.println(st.toString()); //com.mysql.jdbc.JDBC4PreparedStatement@8543aa: select * from goods where min_name = '儿童%'
我们尝试输入了一个百分号,发现PreparedStatement竟然没有转义,百分号恰好是like查询的通配符。
正常情况下,like查询是这么写的:
String sql = "select * from goods where min_name like ?"; // 含有参数
st = conn.prepareStatement(sql);
st.setString(1, "儿童" + "%"); // 参数赋值
System.out.println(st.toString()); //com.mysql.jdbc.JDBC4PreparedStatement@8543aa: select * from goods where min_name like '儿童%'
查询min_name字段以"儿童"开头的所有记录,其中"儿童"二字是用户输入的查询条件,百分号是我们自己加的,怎么可能让用户输入百分号嘛!等等!如果用户非常聪明,偏要输入百分号呢?
String sql = "select * from goods where min_name like ?"; // 含有参数
st = conn.prepareStatement(sql);
st.setString(1, "%儿童%" + "%"); // 参数赋值
System.out.println(st.toString()); //com.mysql.jdbc.JDBC4PreparedStatement@8543aa: select * from goods where min_name like '%儿童%%'
聪明的用户直接输入了"%儿童%",整个查询的意思就变了,变成包含查询。实际上不用这么麻烦,用户什么都不输入,或者只输入一个%,都可以改变原意。
虽然此种SQL注入危害不大,但这种查询会耗尽系统资源,从而演化成拒绝服务攻击。
那如何防范呢?笔者能想到的方案如下:
·直接拼接SQL语句,然后自己实现所有的转义操作。这种方法比较麻烦,而且很可能没有PreparedStatement做的好,造成其他更大的漏洞,不推荐。
·直接简单暴力的过滤掉%。笔者觉得这方案不错,如果没有严格的限制,随便用户怎么输入,既然有限制了,就干脆严格一些,干脆不让用户搜索%,推荐。
目前做搜索,只要不是太差的公司,一般都有自己的搜索引擎(例如著名的java开源搜索引擎solr),很少有在数据库中直接like的,笔者并不是想在like上钻牛角尖,而是提醒读者善于思考,每天都在写着重复的代码,却从来没有停下脚步细细品味。
有读者可能会问,为什么我们不能手动转义一下用户输入的%,其他的再交给PreparedStatement转义?这个留作思考题,动手试一下就知道为什么了。
注意,JDBC只是java定义的规范,可以理解成接口,每种数据库必须有自己的实现,实现之后一般叫做数据库驱动,本文所涉及的PreparedStatement,是由MySQL实现的,并不是JDK实现的默认行为,也就是说,不同的数据库表现不同,不能一概而论。
用java PreparedStatement就不用担心sql注入了吗?的更多相关文章
- 【转载】以Java的视角来聊聊SQL注入
以Java的视角来聊聊SQL注入 原创 2017-08-08 javatiku Java面试那些事儿 在大二就接触过sql注入,之前一直在学习windows逆向技术,认为web安全以后不是自己的从业方 ...
- 重新学习MySQL数据库11:以Java的视角来聊聊SQL注入
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
- PreparedStatement是如何防止SQL注入的?
为什么在Java中PreparedStatement能够有效防止SQL注入?这可能是每个Java程序员思考过的问题. 首先我们来看下直观的现象(注:需要提前打开mysql的SQL文日志) 1. 不使用 ...
- jdbc java数据库连接 8)防止sql注入
回顾下之前jdbc的开发步骤: 1:建项目,引入数据库驱动包 2:加载驱动 Class.forName(..); 3:获取连接对象 4:创建执行sql语句的stmt对象; 写sql 5:执行sql ...
- java学习笔记38(sql注入攻击及解决方法)
上一篇我们写了jdbc工具类:JDBCUtils ,在这里我们使用该工具类来连接数据库, 在之前我们使用 Statement接口下的executeQuery(sql)方法来执行搜索语句,但是这个接口并 ...
- 转!! PreparedStatement是如何防止SQL注入的
SQL注入最简单也是最常见的例子就是用户登陆这一模块,如果用户对SQL有一定的了解,同时系统并没有做防止SQL注入处理,用户可以在输入的时候加上'两个冒号作为特殊字符,这样的话会让计算机认为他输入的是 ...
- XSS过滤JAVA过滤器filter 防止常见SQL注入
Java项目中XSS过滤器的使用方法. 简单介绍: XSS : 跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩 ...
- preparedstatement 为什么可以防止sql注入
有大神总结的很好,,参考文献 http://www.importnew.com/5006.html preparedstatement优势:sql的预编译(数据库层面完成)提升效率. 为什么可以防止s ...
- Java应用开发中的SQL注入攻击
1. 什么是SQL注入攻击? SQL注入攻击是黑客对数据库进行攻击的常用手段之一.随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员越来越多.但是由于程序员的水平及经验参差不齐,相当一部分 ...
随机推荐
- UWP学习记录3-设计和UI之样式
UWP学习记录3-设计和UI之样式 1.颜色 在系统的“设置”>“个性化”>“颜色”里,提供了主题色选择.选定主题色后,会根据颜色亮度的 HSB 值创建浅色和深色的主题色. 应用可使用阴影 ...
- C# ORM中Dto Linq Expression 和 数据库Model Linq Expression之间的转换
今天在百度知道中看到一个问题,研究了一会便回答了: http://zhidao.baidu.com/question/920461189016484459.html 如何使dto linq 表达式转换 ...
- 前端js调用七牛制作评价页面案例
一.需求 公司所有的上传页面都用七牛,前端不免要直接调用七牛的代码进行上传,以下是一个实现七牛上传的案例,制作一个常见的商品评价页面,页面需求很常见当上传到第五章图片的时候,上传按钮消失,上传需要显示 ...
- ActiveMQ
前言 MQ--Message Queue,中文翻译为"消息队列",维基百科上的这样描述: 消息队列(英语:Message queue)是一种进程间通信或同一进程的不同线程间的通信方 ...
- input=text数字问题
其实老干部也会犯错,今天朋友在银行卡账号时候要求输入数字,它的正则竟然排除中文.其实正则是很重要的.废话少说.如果禁止中文呢 ime-mode 但是这个方法兼容性并不是很好,首先我们得知道. css ...
- SQL SERVER 数据导出JSON
执行下面的存储过程: SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE[dbo].[SerializeJSON]( @ ...
- Vue - class与style绑定
1.通过v-bind绑定一个class A:直接绑定 B:通过v-bind绑定一个对象 C:绑定一个返回对象的计算属性 D:绑定一个数组对象 2.绑定内联样式 A:直接子啊属性名上面绑定 B:绑定到一 ...
- sqlite like 通配符 ,匹配区分大小写(默认不区分大小写)
在查询前先执行这个语句 , 1 时区分大小写,0时不区分 PRAGMA case_sensitive_like =0; select prod_name,PROD_PRICEfrom products ...
- iOS分析UI利器——Reveal简单使用
一,简单使用 * 在xcode中打开你的项目(project); * 打开reveal 和选中 Help → Show Reveal Library in Finder * 把Reveal.frame ...
- linux shell输出带颜色文本
echo -e "\033[33;31m Color Text" - red echo -e "\033[33;32m Color Text" - green ...