在 PHP 中使用 SELECT 仅显示单行中的一个值的最安全和正确的解决方案是啥?
Posted
技术标签:
【中文标题】在 PHP 中使用 SELECT 仅显示单行中的一个值的最安全和正确的解决方案是啥?【英文标题】:Which is the most secure and correct solution to display only one value from a single row using SELECT in PHP?在 PHP 中使用 SELECT 仅显示单行中的一个值的最安全和正确的解决方案是什么? 【发布时间】:2014-02-19 18:38:30 【问题描述】:我的问题是,当您只想从 mysql 数据库行中检索一个值时,您认为最好使用哪种解决方案。
例如,假设我们有以下内容:
-table "users"
三行 "username","password" and "status"
和三个用户“user1”、“user2”和“user3”。
如果我只想选择一个用户(比如 user1)的状态并将其设置为变量,我将使用:
$user_status = mysql_result(mysql_query("SELECT status FROM users WHERE username='user1'"),0);
我在网上搜索,发现人们使用不同的方法来检索此类信息,例如在选择代码中设置 LIMIT 1 或检索整个用户列表,然后对符合他们需求的列表进行排序。
我想知道我的解决方案是否是最好和最安全的方法(包括 SQL 注入的安全性,请记住在 php 代码中没有使用 $_GET
方法)。
也许同时使用LIMIT 1
和我上面使用的方法(代码需要更少的资源和时间来执行)?
【问题讨论】:
这里的sql注入有什么注意事项?如果您不使用用户输入,那么这应该是不可能的。虽然我想知道你想怎么做,因为你必须以某种方式指定你当前正在测试的用户...... 或者你可以使用 PDO 和存储过程....不要使用 mysql 扩展,使用 mysqli 或 PDO 【参考方案1】:从数据库的角度来看,最安全的方法是在您从中选择的表中拥有一个唯一键,并通过该键检索行。在您的示例中,您可以有一个 userID 列,其中包含每个用户的唯一 ID。如果您查询WHERE userID='...'
,数据库保证您只能有一个结果行。
编辑:“舆论”建议我添加两件事。
-
你不能使用mysql_*!为什么不使用mysqli?您不必担心its performance。
如果您使用正确的数据库设计,则没有理由使用
LIMIT 1
- 完全没有理由。这有点像写代码Enter car; Make sure you have entered exactly one car;
。 LIMIT
可用于其他情况,例如检索多个结果的前 10 个。
【讨论】:
您还应该提及放弃已弃用的mysql_*
并采用mysqli
,或者最好是pdo
我相信这是某种登录系统,所以这里不能使用 ID。
我刚刚发布了一个基本示例,所以我希望得到一个一般性的答案,而不是一个具体的答案。话虽这么说:@SebastianH - 我知道如何确保只有一个具有上述值的字段,问题是如何更干净、更快速地检索它。另外,我使用 mysql,但我知道 mysqli 是我想要使用的。谢谢提醒。
如果您关心性能(除非这是非常关键的情况,否则您不应该关心)然后 - 再次从数据库的角度来看 - 一个关键是重要的。我想我不必讲从根本没有键的列中检索数据 -> 全表扫描。 @Андрей Почекуев 在这种情况下,拥有一个相同的唯一用户名至关重要。【参考方案2】:
第一个 - 您不再使用 mysql_
方法 - 它们已被弃用并且本身不安全。
第二 - 你使用 PDO 接口,像这样
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'dbuser';
$password = 'dbpass';
try
$dbh = new PDO($dsn, $user, $password);
$stmt = $dbh->prepare("SELECT `status` FROM `users` WHERE `username` = ?");
$stmt->execute(array($_GET['username']));
$status = $stmt->fetchColumn();
catch (PDOException $e)
echo 'PDO Error : ' . $e->getMessage();
使用prepare
- execute
链对 PDO 是安全的 - 它会自动清理,因此您不必担心 mysql 注入。在prepare
部分,您使用参数创建查询,在execute
部分,您使用等于$_GET
的参数执行准备好的查询并存储结果。您在此过程中遇到的任何错误都会被 catch (PDOException $e)
块捕获,并且可以得到适当的处理。
【讨论】:
【参考方案3】:如果你想要任何安全性,你应该使用 PDO 方法,常规的 mysql 调用已经消失了一段时间
使用 mysqli (http://ee1.php.net/mysqli),但在这里查看http://www.php.net/manual/en/book.pdo.php
您的查询将是 SELECT status
FROM users
WHERE username
='user1' LIMIT 1
【讨论】:
以上是关于在 PHP 中使用 SELECT 仅显示单行中的一个值的最安全和正确的解决方案是啥?的主要内容,如果未能解决你的问题,请参考以下文章
如何根据 WHERE 条件使用 mysqli 进行 SELECT 和 DELETE 和 RETURN 单行
迭代 Django 中的相关对象:循环查询集或使用单行 select_related(或 prefetch_related)