[转载]mysql绑定参数bind_param原理以及防SQL注入
假设我们的用户表中存在一行.用户名字段为username.值为aaa.密码字段为pwd.值为pwd..
下面我们来模拟一个用户登录的过程..
- <?php
- $username = "aaa";
- $pwd = "pwd";
- $sql = "SELECT * FROM table WHERE username = '{$username}' AND pwd = '{$pwd}'";
- echo $sql; //输出 SELECT * FROM table WHERE username = 'aaa' AND pwd = 'pwd'
- ?>
这样去执行这个sql语句.显然是可以查询出来东西的.返回用户的这一列.登录成功!!
然后我改一下..把密码改一下.随便一个值.如下.我改成了ppp.
- <?php
- $pwd = 'ppp';
- $sql = "SELECT * FROM table WHERE username = '{$username}' AND pwd = '{$pwd}'";
- echo $sql; //输出 SELECT * FROM table WHERE username = 'aaa' AND pwd = 'ppp'
- ?>
这样很显然.如果去执行这个SQL语句..是查询不到东西的.也就是密码错误.登录失败!!
但是有的人总是不老实的.他们会想尽一切办法来进行非法的登录.所谓非法就是在他不知道用户名密码的时候进行登录.并且登录成功..
那么他们所做的原理是什么呢??其实原理都是利用SQL语句..SQL语句强大的同时也给我们带来了不少麻烦..
我来举个最简单的例子.我们要运用到的SQL关键字是or
还是上面的代码.我们只要修改一下密码即可
- <?php
- $username = "aaa";
- $pwd = "fdsafda' or '1'='1"; //前面的密码是瞎填的..后来用or关键字..意思就是无所谓密码什么都执行
- $sql = "SELECT * FROM table WHERE username = '{$username}' AND pwd = '{$pwd}'";
- echo $sql; //输出 SELECT * FROM table WHERE username = 'aaa' AND pwd = 'fdsafda' or '1'='1'
- ?>
执行一下这个SQL语句..可怕的事情发生了..竟然可以查询到这一行数据..也就是登录成功了..
这是多么可怕的事情..
SQL注入演示教程,见博文:http://blog.csdn.net/wusuopubupt/article/details/8818996
PHP为了解决这个问题.magic_quotes state..就是PHP会自动过滤传过来的GET.POST等等.
题外话.实践证明这个东西是畸形的..大部分程序不得不为判断此功能而耗费了很多代码..
在Java中可没有这个东西..那么Java中如何防止这种SQL注入呢??
Java的sql包中提供了一个名字叫PreparedStatement的类.
这个类就是我要说的绑定参数!
什么叫绑定参数??我继续给大家举例..(我用PHP举例)
- <?php
- $username = "aaa";
- $pwd = "pwd";
- $sql = "SELECT * FROM table WHERE username = ? AND pwd = ?";
- bindParam($sql, 1, $username, 'STRING'); //以字符串的形式.在第一个问号的地方绑定$username这个变量
- bindParam($sql, 2, $pwd, 'STRING'); //以字符串的形式.在第二个问号的地方绑定$pwd这个变量
- echo $sql;
- ?>
当然.到此.你肯定不知道会输出什么..更无法知道绑定参数有什么好处!这样做的优势是什么.更不知道bindParam这个函数到底做了什么.
下面我简单的写一下这个函数:
- <?php
- /**
- * 模拟简单的绑定参数过程
- *
- * @param string $sql SQL语句
- * @param int $location 问号位置
- * @param mixed $var 替换的变量
- * @param string $type 替换的类型
- */
- $times = 0;
- //这里要注意,因为要“真正的"改变$sql的值,所以用引用传值
- function bindParam(&$sql, $location, $var, $type) {
- global $times;
- //确定类型
- switch ($type) {
- //字符串
- default: //默认使用字符串类型
- case 'STRING' :
- $var = addslashes($var); //转义
- $var = "'".$var."'"; //加上单引号.SQL语句中字符串插入必须加单引号
- break;
- case 'INTEGER' :
- case 'INT' :
- $var = (int)$var; //强制转换成int
- //还可以增加更多类型..
- }
- //寻找问号的位置
- for ($i=1, $pos = 0; $i<= $location; $i++) {
- $pos = strpos($sql, '?', $pos+1);
- }
- //替换问号
- $sql = substr($sql, 0, $pos) . $var . substr($sql, $pos + 1);
- }
- ?>
注:由于得知道去除问号的次数..所以我用了一个global来解决.如果放到类中就非常容易了.弄个私有属性既可
通过上面的这个函数.我们知道了..绑定参数的防注入方式其实也是通过转义进行的..只不过是对于变量而言的..
我们来做一个实验:
- <?php
- $times = 0;
- $username = "aaaa";
- $pwd = "123";
- $sql = "SELECT * FROM table WHERE username = ? AND pwd = ?";
- bindParam($sql, 1, $username, 'STRING'); //以字符串的形式.在第一个问号的地方绑定$username这个变量
- bindParam($sql, 2, $pwd, 'INT'); //以字符串的形式.在第二个问号的地方绑定$pwd这个变量
- echo $sql; //输出 SELECT * FROM table WHERE username = 'aaaa' AND pwd = 123
- ?>
可以看到.生成了非常正规的SQL语句.那么好.我们现在来试下刚才被注入的那种情况
- <?php
- $times = 0;
- $username = "aaa";
- $pwd = "fdsafda' or '1'='1";
- $sql = "SELECT * FROM table WHERE username = ? AND pwd = ?";
- bindParam($sql, 1, $username, 'STRING'); //以字符串的形式.在第一个问号的地方绑定$username这个变量
- bindParam($sql, 2, $pwd, 'STRING'); //以字符串的形式.在第二个问号的地方绑定$pwd这个变量
- echo $sql; //输出 SELECT * FROM table WHERE username = 'aaa' AND pwd = 'fdsafda\' or \'1\'=\'1'
- ?>
可以看到.pwd内部的注入已经被转义.当成一个完整的字符串了..这样的话.就不可能被注入了.
原文地址 :http://hi.baidu.com/woyigui/item/afc6ec2efaa49f0f73863e2e
参考:http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php
[转载]mysql绑定参数bind_param原理以及防SQL注入的更多相关文章
- mysql绑定参数bind_param原理以及防SQL注入
假设我们的用户表中存在一行.用户名字段为username.值为aaa.密码字段为pwd.值为pwd.. 下面我们来模拟一个用户登录的过程.. <?php $username = "aa ...
- 回头探索JDBC及PreparedStatement防SQL注入原理
概述 JDBC在我们学习J2EE的时候已经接触到了,但是仅是照搬步骤书写,其中的PreparedStatement防sql注入原理也是一知半解,然后就想回头查资料及敲测试代码探索一下.再有就是我们在项 ...
- 【荐】PDO防 SQL注入攻击 原理分析 以及 使用PDO的注意事项
我们都知道,只要合理正确使用PDO,可以基本上防止SQL注入的产生,本文主要回答以下几个问题: 为什么要使用PDO而不是mysql_connect? 为何PDO能防注入? 使用PDO防注入的时候应该特 ...
- golang 防SQL注入 基于反射、TAG标记实现的不定参数检查器
收到一个任务,所有http的handler要对入参检查,防止SQL注入.刚开始笨笨的,打算为所有的结构体写一个方法,后来统计了下,要写几十上百,随着业务增加,以后还会重复这个无脑力的机械劳作.想想就l ...
- PDO防 SQL注入攻击 原理分析 以及 使用PDO的注意事项
我们都知道,只要合理正确使用PDO(PDO一是PHP数据对象(PHP Data Object)的缩写),可以基本上防止SQL注入的产生,本文主要回答以下几个问题: 为什么要使用PDO而不是mysql_ ...
- mysql之数据库连接的方法封装及防sql注入
一.定义数据库和表 create database animal; CREATE TABLE `pet` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name ...
- 【转载】C#防SQL注入过滤危险字符信息
不过是java开发还是C#开发或者PHP的开发中,都需要关注SQL注入攻击的安全性问题,为了保证客户端提交过来的数据不会产生SQL注入的风险,我们需要对接收的数据进行危险字符过滤来防范SQL注入攻击的 ...
- PHP防SQL注入不要再用addslashes和mysql_real_escape_string
PHP防SQL注入不要再用addslashes和mysql_real_escape_string了,有需要的朋友可以参考下. 博主热衷各种互联网技术,常啰嗦,时常伴有强迫症,常更新,觉得文章对你有帮助 ...
- JDBC及PreparedStatement防SQL注入
概述 JDBC在我们学习J2EE的时候已经接触到了,但是仅是照搬步骤书写,其中的PreparedStatement防sql注入原理也是一知半解,然后就想回头查资料及敲测试代码探索一下.再有就是我们在项 ...
随机推荐
- 一.windows环境下rabbitMQ的的安装和配置
rabbitMQ是AMQP 0-9-1(高级消息队列协议)的一个实现,使用Erlang语言编写,利用了Erlang的分布式特性.用它来实现分布式消息队列. 1.因为是用Erlang编写的,所以首先要安 ...
- IntelliJ Idea 2017 注册码 免费激活方法
1. 到网站 http://idea.lanyus.com/ 获取注册码. 2.弹窗中选择最后一个页面license server,填入下面一种链接即可: http://idea.iteblog.co ...
- dedecms在php7下的使用方法,织梦dedecsm后台一片空白的解决方法
前几天,一个老客户,最近升级了服务器,php到php7,把织梦dedecms转移到新服务器后,不能登录后台,让帮忙看一下. 我看了下他们的网站,使用的是织梦V57_UTF8_SP1前台页面是可以访问的 ...
- AsyncLocal的运作机制和陷阱
这是今天帮柠檬分析一个AsyncLocal相关的问题时发现的. 试想这个代码输出的值是多少? using System; using System.Threading; using System.Th ...
- Apache反向代理的配置
Apache反向代理的配置 一: Mac系统自带apache服务器 1. 查看apache版本命令如下: sudo apachectl -v 2. 启动apache sudo apachect ...
- HTML基础教程-标题
HTML 标题 在 HTML 文档中,标题很重要. HTML 标题 标题(Heading)是通过 <h1> - <h6> 等标签进行定义的. <h1> 定义最大的标 ...
- Struts2学习---result结果集
这一章节主要介绍如何配置结果集,分为以下几个知识点: 结果集类型(result type) 全局结果集(global types) 动态结果集(dynamic type) 带有参数的结果集(type ...
- Fiori缓存与它的清除
最近在修改已有的Fiori应用,遇到了缓存上的一点问题,导致对Fiori应用的代码修改不能在前端页面生效.现将自己查到的一篇好资料翻译过来,以供参考.以下为正文. 2017.12.19更新:最近又遇到 ...
- python学习日记:day11----装饰器进阶
1.wraps from functools import wraps def wrapper(func): #func = holiday @wraps(func)#输出holiday的函数名 de ...
- VisualVM 分析full GC问题记录
背景:JAVA APP,主要功能是处理日志并存入db 现象:运行一段时间就出现OOM问题,查看GC log发现运行没多久就一直Full GC,并且抛出OOM的异常. [Full GC (Ergonom ...