2017-07-25 PDO预处理以及防止sql注入

首先来看下不做任何处理的php登录,首先是HTML页面代码

<html>
    <head><title>用户登录</title></head>
    <body>
        <fieldset>
        <legend><h3>用户登录</h3></legend>
        <form action="user_login_pro.php" method="post">
        用户账号:<input type="text" name="name"><br><br>
        用户密码:<input type="password" name="password"><br><br>
        <input type="submit" value="登录">
        </form>
        </fieldset>
    </body>
</html>

其次是php处理代码:

//引入PDO连库文件
require './database/db.php';

$name = $_POST['name'];
$password = $_POST['password'];
$sql = "select * from user where name ='{$name}' and password ='{$password}'";
$res = $pdo->query($sql);
$row = $res->fetch(PDO::FETCH_ASSOC);

if($row){
 
    echo "login success";
 }else{
    echo "login error";
 }

页面效果:

 从上面的代码可见,我们输入账户名密码后,进入处理页面,与数据库作对比,如果账号密码都正确的情况之下,输出login success ,错误则输出login error。运行效果也正常,但如果我们在账户名处输入如下代码【' or 1=1 #】也会输出login success。这就是sql注入,通过一些代码改变了我们的sql语句,我们输出一次sql语句是什么样子的呢?select * from user where name ='' or 1=1 #' and password ='';可以发现这条sql语句变成了恒成立的语句,诸如此类的方式其实有很多,那么我们怎么防止sql注入呢?

1.使用pdo预处理

//1.准备预处理语句
 $sql = "select * from user where name =? and password =?";
 $res = $pdo->prepare($sql);

 //2.绑定参数
 $name = $_POST['name'];
 $password = $_POST['password'];

 $res->bindParam(1,$name);
 $res->bindparam(2,$password);

 //3.执行预处理语句
 $res->execute();


//4.转成一条结果
 $row = $res->fetch(PDO::FETCH_ASSOC);

//5.判断
if($row){
    echo "login success";
}else{
    echo "login error";
}

我们用?占位符把公共的操作部分 与 可变的数据部分相分离。根据上面的步骤执行一遍,再用 【' or 1=1 #】去测试,输出login error。成功防止。

 2.addslashes()函数转义

$name = addslashes($_POST['name']);
$password = $_POST['password'];
$sql = "select * from user where name ='{$name}' and password ='{$password}'";
//print_r($sql);die();
$res = $pdo->query($sql);
$row = $res->fetch(PDO::FETCH_ASSOC);

if($row){
 
    echo "login success";
 }else{
    echo "login error";
 }

 还用上面的sql注入,结果也是失败的。证明防止成功。addslashes() 函数在指定的预定义字符前添加反斜杠。这些字符是单引号(')、双引号(")、反斜线(\)与NUL(NULL字符)。在使用这种方式后,sql语句就变为了:select * from user where name ='\' or 1=1 #' and password ='1234567';

3.intval()

在很多时候我们要用到类似xxx.php?id=xxx这样的URL,一般来说$id都是整型变量,为了防范攻击者把$id篡改成攻击语句,我们要尽量强制变量,PHP防范SQL注入的代码$id=intval($_GET['id']);

//intval() 防止整数类型被改变
$id="abc123";
echo intval($id);

输出结果为0;可以知道intval()可以将字符串转成整数,故而可以防止整数类型被改变。 

猜你喜欢

转载自www.cnblogs.com/zhangxu-fasu/p/11245886.html