php 如何将参数绑定到未准备好的查询?

mhd8tkvw  于 2023-02-18  发布在  PHP
关注(0)|答案(3)|浏览(145)

我正在做一个小的网络应用程序,它将定期接收用户输入的数据,当我研究如何确保数据输入首先被清理时,似乎预准备语句是一条可行之路。
然而,我找到了this SO question,并且由于我的应用程序(至少据我所知)不会对每个页面请求执行多个查询,因此我真正需要的似乎只是将值绑定到查询中的参数。
我已经浏览了有关PDO和mysqli的PHP手册,但是我找不到任何将值绑定到普通查询的示例,我找到的所有示例在绑定之前都有一个$stmt->prepare
语句是否"准备好"是由数据库的支持来决定的吗?准备语句总是在代码中吗?或者有没有办法直接将参数绑定到$dbh->query(...)中?
为了解释为什么我想看看是否有可能不使用prepare,是因为我在文章前面链接的SO问题中的这句话:
什么时候不使用预准备语句?什么时候在数据库连接断开之前只运行一次预准备语句。
什么时候不使用绑定查询参数(这实际上是大多数人使用预准备语句获得的)?
还有这个
就我个人而言,我不想麻烦。伪预准备语句可能对它们可能提供的安全变量引用很有用。

ilmyapht

ilmyapht1#

如何将参数绑定到未准备好的查询?
你不需要。一个带有参数的SQL字符串(例如在特定位置的问号)需要先被解析(例如 * prepared *),然后这些问号才能被视为参数值的插入点。
因此,在调用bind()之前,您始终需要调用prepare()

    • 参数化语句**是包含SQL和占位符标记(例如问号,但不同的数据库使用不同的占位符)的字符串:
$sql = "SELECT user_id FROM user WHERE user_name = ?"

现在假设有一个value要插入到这个位置:

$_POST["username"]
    • 准备一个语句**,一般来说,问号有特殊的含义 "a value can be insert here"。换句话说,它从占位符创建了 * parameters *。
$stmt->prepare($sql)
    • 将值绑定到参数**将参数设置为特定值。
$stmt->bind_param("s", $_POST["username"])

现在,查询可以在SQL字符串和用户提供的值不发生实际接触的情况下执行。**这是很重要的一点:**SQL和参数值是分别发送到服务器的,它们从不接触。

$stmt->execute();

其优点是:

  • 您可以将新值绑定到参数并再次执行查询,而不必重复所有操作(在循环中很有用)。
  • 无论$_POST["username"]包含什么值,SQL注入都是不可能的。
7vhp5slm

7vhp5slm2#

你不知道。原因如下:
如果使用$dbh->query(...),则只需调用sql,并将参数插入到sql字符串中。

$dbh->query("INS INTO MY_TABLE_OF_NAMES ('$name');");

大约10年前,大多数sql都是这样做的。这是调用数据库的最直接的方式,使用RDMS已经实现的SQL接口,而不需要特殊的底层接口。但人们发现这是危险的,因为有一种叫做SQL注入的东西。
http://en.wikipedia.org/wiki/Sql_injection
最简单也是最常见的例子是这样的:假设你的网页中有一个SQL调用,它将运行:

INS INTO MY_TABLE_OF_NAMES VALUE ('$name');

但是,有人会访问您的站点并输入名称bob'); DROP TABLE MY_TABLE_OF_NAMES;
你的插入SQL语句突然变成了

INS INTO MY_TABLE_OF_NAMES VALUE ('bob'); DROP TABLE MY_TABLE_OF_NAMES; );

这将随后将bob插入到您的数据库中,删除您的所有名字,并在您的网站运行它时抛出尾随);的错误。
因此,预准备语句被发明了,它不是直接在字符串中插入字符串,而是使用?字符来表示动态值,bind函数用于安全地插入字符串,这样恶意输入就不会被数据库引擎解释为SQL代码,您的站点也不会被欺骗去做它不想做的事情。prepare命令接受一个SQL字符串,接受一点SQL,然后semi编译成一种低级数据库语言,在使用?的地方留下动态字符串的空白,然后Bind接受其中一个空白,并用一段数据填充,编码为转义的ascii,这样它就不会被误解为SQL代码。一旦所有这些?都被填充,SQL就可以发送到RDMS运行了。
因此,回答你的问题,你永远不会绑定一个参数到一个简单的查询。如果你想在一个简单的查询动态变量,你只会插入到SQL字符串。但这是危险的。预准备语句允许你预编译一个SQL语句,然后安全地绑定动态参数到它,以创建安全的动态SQL。绑定到SQL纯粹是一个预准备语句的构造。

kyks70gy

kyks70gy3#

为了使用绑定参数,你必须使用预准备语句,这只是目前在pdo和mysqli中实现的方式,我不确定是否某些数据库产品支持某种类型的通信协议,其中参数化sql(使用占位符的SQL文本)与参数值沿着发送而不必首先进行显式的准备调用,但是pdo和mysqli并没有公开这个功能,这对于web应用来说肯定是一个受欢迎的特性。
对于pdo,是的,当你调用$dbh->prepare($sql)时,sql语句是否真正准备好了,这取决于数据库的支持。当数据库不支持预准备语句时,pdo会模拟预准备语句,或者如果配置了的话,它总是可以模拟预准备语句。事实上,默认情况下,pdo会模拟mysql驱动程序的预准备语句。并且在很长一段时间内默认都是这样做的。它通过创建动态sql,引用值来模拟它们,就像您所做的那样。在本例中,sql(最终值嵌入到文本中)在调用$stmt->execute()时被发送到数据库。是的,在某些情况下,sql注入是可能的。

相关问题