我正在做一个小的网络应用程序,它将定期接收用户输入的数据,当我研究如何确保数据输入首先被清理时,似乎预准备语句是一条可行之路。
然而,我找到了this SO question,并且由于我的应用程序(至少据我所知)不会对每个页面请求执行多个查询,因此我真正需要的似乎只是将值绑定到查询中的参数。
我已经浏览了有关PDO和mysqli的PHP手册,但是我找不到任何将值绑定到普通查询的示例,我找到的所有示例在绑定之前都有一个$stmt->prepare
。
语句是否"准备好"是由数据库的支持来决定的吗?准备语句总是在代码中吗?或者有没有办法直接将参数绑定到$dbh->query(...)
中?
为了解释为什么我想看看是否有可能不使用prepare,是因为我在文章前面链接的SO问题中的这句话:
什么时候不使用预准备语句?什么时候在数据库连接断开之前只运行一次预准备语句。
什么时候不使用绑定查询参数(这实际上是大多数人使用预准备语句获得的)?
还有这个
就我个人而言,我不想麻烦。伪预准备语句可能对它们可能提供的安全变量引用很有用。
3条答案
按热度按时间ilmyapht1#
如何将参数绑定到未准备好的查询?
你不需要。一个带有参数的SQL字符串(例如在特定位置的问号)需要先被解析(例如 * prepared *),然后这些问号才能被视为参数值的插入点。
因此,在调用
bind()
之前,您始终需要调用prepare()
。现在假设有一个value要插入到这个位置:
现在,查询可以在SQL字符串和用户提供的值不发生实际接触的情况下执行。**这是很重要的一点:**SQL和参数值是分别发送到服务器的,它们从不接触。
其优点是:
$_POST["username"]
包含什么值,SQL注入都是不可能的。7vhp5slm2#
你不知道。原因如下:
如果使用
$dbh->query(...)
,则只需调用sql,并将参数插入到sql字符串中。大约10年前,大多数sql都是这样做的。这是调用数据库的最直接的方式,使用RDMS已经实现的SQL接口,而不需要特殊的底层接口。但人们发现这是危险的,因为有一种叫做SQL注入的东西。
http://en.wikipedia.org/wiki/Sql_injection
最简单也是最常见的例子是这样的:假设你的网页中有一个SQL调用,它将运行:
但是,有人会访问您的站点并输入名称
bob'); DROP TABLE MY_TABLE_OF_NAMES;
你的插入SQL语句突然变成了
这将随后将bob插入到您的数据库中,删除您的所有名字,并在您的网站运行它时抛出尾随
);
的错误。因此,预准备语句被发明了,它不是直接在字符串中插入字符串,而是使用
?
字符来表示动态值,bind
函数用于安全地插入字符串,这样恶意输入就不会被数据库引擎解释为SQL代码,您的站点也不会被欺骗去做它不想做的事情。prepare命令接受一个SQL字符串,接受一点SQL,然后semi编译成一种低级数据库语言,在使用?
的地方留下动态字符串的空白,然后Bind接受其中一个空白,并用一段数据填充,编码为转义的ascii,这样它就不会被误解为SQL代码。一旦所有这些?
都被填充,SQL就可以发送到RDMS运行了。因此,回答你的问题,你永远不会绑定一个参数到一个简单的查询。如果你想在一个简单的查询动态变量,你只会插入到SQL字符串。但这是危险的。预准备语句允许你预编译一个SQL语句,然后安全地绑定动态参数到它,以创建安全的动态SQL。绑定到SQL纯粹是一个预准备语句的构造。
kyks70gy3#
为了使用绑定参数,你必须使用预准备语句,这只是目前在pdo和mysqli中实现的方式,我不确定是否某些数据库产品支持某种类型的通信协议,其中参数化sql(使用占位符的SQL文本)与参数值沿着发送而不必首先进行显式的准备调用,但是pdo和mysqli并没有公开这个功能,这对于web应用来说肯定是一个受欢迎的特性。
对于pdo,是的,当你调用
$dbh->prepare($sql)
时,sql语句是否真正准备好了,这取决于数据库的支持。当数据库不支持预准备语句时,pdo会模拟预准备语句,或者如果配置了的话,它总是可以模拟预准备语句。事实上,默认情况下,pdo会模拟mysql驱动程序的预准备语句。并且在很长一段时间内默认都是这样做的。它通过创建动态sql,引用值来模拟它们,就像您所做的那样。在本例中,sql(最终值嵌入到文本中)在调用$stmt->execute()
时被发送到数据库。是的,在某些情况下,sql注入是可能的。