前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Mysqli使用bind_param()防止SQL注入的原理

Mysqli使用bind_param()防止SQL注入的原理

作者头像
躺平程序员老修
发布2023-09-05 15:33:51
3820
发布2023-09-05 15:33:51
举报

mysql sql注入 进阶

今天偶然看了一篇博文,说是一道php面试笔试题,原文如下:

请找出下面代码中的问题,修复并优化 <?php //批量注册用户,每次>100个。 //注册新用户,要求用户名与email不能与以前的重复。 $mysqli = new Mysqli($host, $user, $pass); for ($i=0; $i<count($_POST['user_info']); $i++) { $info = $_POST['user_info'][$i]; $re_1 = $mysqli->query("SELECT * FROM `demo` WHERE `uname`=$info['uname']"); $re_2 = $mysqli->query("SELECT * FROM `demo` WHERE `email`=$info['email']"); if (!$re_1 || !$re_2) { $mysqli->query("INSERT INTO `demo` (`uname`, `email`) VALUES('$info['email']', '$info['uname']')"); } }``` 答案: 基础:应该把count提到循环外。 基础:在字符串中拼装数组时候应该用 { 与 } 括起来。 基础:!$re_1 || $re_2应该是!$re_1 && !$re_2或者!($re_1 || $re_2)。 基础:insert语句的values部分两个字段顺序错了。 性能:uname与email两个语句应该拼装成一个OR语句。 性能:应该把所有SELECT拼装一个Sql,然后去除冲突的,再把剩余的通过批量插入的方式通过一条Sql插入。 性能:for应该该用foreach。 安全:参数没有过滤,但回答htmlspecialchars\addslashes而非mysqli->real_escape_string的减分。 其它:query前没有USE database之类的操作,没有SET NAMES,能回答上来的比较细心。 其它:没有错误处理。

特意看了一下,是2013年的文章,所以不做过多评论,(mysqli连接少了一个参数,原文如此)。该题给出的答案并不太令人满意,通过这道题让我想到的是,应该怎么做才能尽量避免SQL注入?

使用mysqli批处理技术,bind_param()

代码语言:javascript
复制
<?php
$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'world');

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
$stmt->bind_param('sssd', $code, $language, $official, $percent);

$code = 'DEU';
$language = 'Bavarian';
$official = "F";
$percent = 11.2;

/* execute prepared statement */
$stmt->execute();

printf("%d Row inserted.\n", $stmt->affected_rows);

/* close statement and connection */
$stmt->close();

/* Clean up table CountryLanguage */
$mysqli->query("DELETE FROM CountryLanguage WHERE Language='Bavarian'");
printf("%d Row deleted.\n", $mysqli->affected_rows);

/* close connection */
$mysqli->close();
?>

参数说明:

  • i corresponding variable has type integer 整数
  • d corresponding variable has type double 浮点型小数
  • s corresponding variable has type string 字符串
  • b corresponding variable is a blob and will be sent in packets 二进制包

原理说明:为什么bind_param()可以防止SQL注入?

  1. 使用了占位符(“?”):无论传多少值都是安全的,因为她已经被定义成一个参数,而非一条语句的部分;
  2. 预编译模式:在数据库层已经被编译成特定的执行方式,如select、insert等,不会因为后续的参数而改变执行方式;
  3. 内部自动转义特殊字符。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 今天偶然看了一篇博文,说是一道php面试笔试题,原文如下:
  • 使用mysqli批处理技术,bind_param()
  • 原理说明:为什么bind_param()可以防止SQL注入?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档