在 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 单行

MySQL:将单行显示为列(简单地说,通过 SELECT)

迭代 Django 中的相关对象:循环查询集或使用单行 select_related(或 prefetch_related)

dumpe2fs仅显示单行消息

在长文本通知的情况下,MI/XIAOMI 手机上仅显示单行(修剪文本)

使用 ForEach SwiftUI Core Data 仅更改列表中的一项