开发者社区> 问答> 正文

用PDO和准备好的语句替换mysql_ *函数?mysql

我一直在做的简单连接mysql_connect,mysql_pconnect:

$db = mysql_pconnect('host', 'user', 'pass');

if (!$db) { echo("Error: Could not connect to the database!"); exit; }

mysql_select_db('database'); 虽然使用这个我一直使用的简单的方法,使查询之前逃脱的任何数据,不管是INSERT,SELECT,UPDATE或者DELETE通过使用mysql_real_escape_string

$name = $_POST['name'];

$name = mysql_real_escape_string($name);

$sql = mysql_query("SELECT * FROM users WHERE (name = '$name')") or die(mysql_error()); 现在我知道这在一定程度上是安全的!

它逃脱了危险人物;但是,它仍然容易受到其他攻击的攻击,这些攻击可能包含安全字符,但可能有害于显示数据或在某些情况下恶意修改或删除数据。

因此,我进行了一些搜索,以了解有关PDO,MySQLi和准备好的语句的信息。是的,我可能迟到了游戏,但是我读了很多很多教程(tizag,W3C,博客,Google搜索),但没有一个提到这些。关于原因,这似乎很奇怪,因为逃避用户输入确实是不安全的,至少可以说不是一种好习惯。是的,我知道您可以使用Regex来解决它,但是,我很确定那还不够吗?

据我了解,当变量由用户输入指定时,使用PDO /预处理语句是从数据库存储和检索数据的更安全的方法。唯一的麻烦是,切换(特别是在以我以前的编码方式/习惯非常困住之后)有点困难。

现在我知道使用PDO连接到数据库

$hostname = 'host'; $username = 'user'; $password = 'pass'; $database = 'database'

$dbh = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);

if ($dbh) { echo 'Connected to database'; } else { echo 'Could not connect to database'; } 现在,函数名是不同的,因此将不再我mysql_query,mysql_fetch_array,mysql_num_rows等工作。因此,我必须阅读/记住大量新内容,但这是我感到困惑的地方。

如果我想从注册/注册表格中插入数据,我将如何去做,但主要是如何安全地去做呢?我假设这是准备好的语句出现的地方,但是通过使用它们,这消除了使用诸如之类的东西的需要mysql_real_escape_string。我知道这mysql_real_escape_string要求您通过mysql_connect/ 连接到数据库,mysql_pconnect所以现在我们既不使用它,也不会产生错误吗?

我也看到了采用PDO方法的不同方法,例如,我已经看到了,:variable并且?我认为这被称为占位符(抱歉,如果那是错误的话)。

但是我认为这大致是应该从数据库中获取用户的想法。

$user_id = $_GET['id']; // For example from a URL query string

$stmt = $dbh->prepare("SELECT * FROM users WHERE id = :user_id");

$stmt->bindParam(':user_id', $user_id, PDO::PARAM_INT); 但是,接下来我会停留在一些事情上,如果变量不是数字,而是文本字符串,那么PDO:PARAM_STR如果我没有记错的话,必须给定一个长度。但是,如果不确定用户输入的数据所给出的值,则该长度如何设置呢?无论哪种方式,据我所知显示您随后要做的数据

$stmt->execute();

$result = $stmt->fetchAll();

// Either

foreach($result as $row) { echo $row['user_id'].'
'; echo $row['user_name'].'
'; echo $row['user_email']; }

// Or

foreach($result as $row) { $user_id = $row['user_id']; $user_name = $row['user_name']; $user_email = $row['user_email']; }

echo("".$user_id."
".$user_name."
".$user_email.""); 现在,这一切安全吗?

如果我是对的,则插入数据是否会相同,例如:

$username = $_POST['username']; $email = $_POST['email'];

$stmt = $dbh->prepare("INSERT INTO users (username, email) VALUES (:username, :email)");

$stmt->bindParam(':username, $username, PDO::PARAM_STR, ?LENGTH?); $stmt->bindParam(':email, $email, PDO::PARAM_STR, ?LENGTH?);

$stmt->execute(); 那行得通吗,那也安全吗?如果是正确的话,我会为值多少钱?LENGTH??我把这完全弄错了吗?

更新

到目前为止,我的回复非常有帮助,不能谢谢你们!每个人都可以通过+1使我睁开眼睛,看到有些不同。选择最佳答案很困难,但我认为Shrapnel上校应有尽有,因为几乎所有内容都已覆盖,甚至使用我不知道的自定义库进入其他阵列!

但是感谢大家:)

展开
收起
保持可爱mmm 2020-05-17 19:57:22 1228 0
1 条回答
写回答
取消 提交回答
  • 感谢您提出有趣的问题。干得好:

    它逃脱了危险人物,

    您的概念完全错误。 实际上“危险人物”是神话,没有神话。和mysql_real_escape_string转义,但只是一个字符串定界符。从这个定义中,您可以得出它的局限性-仅适用于string。

    但是,它仍然容易受到其他攻击的攻击,这些攻击可能包含安全字符,但可能有害于显示数据或在某些情况下恶意修改或删除数据。

    您在这里混合了所有内容。 说到数据库,

    对于字符串,它不是脆弱的。只要您的字符串被引用和转义,它们就不能 “恶意修改或删除数据”。* 对于其他数据类型data-是的,它没有用。但这不是因为它“不安全”,而是因为使用不当。 至于显示数据,我认为它在与PDO有关的问题中是题外话,因为PDO也与显示数据无关。

    转义用户输入

    ^^^另一个需要注意的错觉!

    用户输入与转义绝对无关。从前一个定义中可以了解到,您必须转义字符串,而不是“用户输入”。因此,再次:

    您有转义字符串,无论其来源如何 无论源如何,都无法逃脱其他类型的数据。 明白了吗? 现在,我希望您了解转义的局限性以及“危险人物”的误解。

    据我了解,使用PDO /预备语句更安全

    并不是的。 实际上,我们可以动态添加四个不同的查询部分:

    一个字符串 一个号码 标识符 语法关键字。 因此,您可以看到转义仅涵盖一个问题。(但是,当然,如果将数字视为字符串(用引号引起来),则在适用时也可以使其安全)

    而准备好的语句涵盖了-嗯-全部2个问题!很大;-)

    对于其他两个问题,请参阅我的早期答案:在PHP中,在向数据库提交字符串时,我应该使用htmlspecialchars()还是使用正则表达式来处理非法字符?

    现在,函数名称有所不同,因此我的mysql_query,mysql_fetch_array,mysql_num_rows等不再起作用。

    那是PHP 用户的另一种严重的幻想,一种自然灾害,一场灾难:

    即使使用旧的mysql驱动程序,也永远不要在其代码中使用裸露的API函数!必须将它们放在某种库函数中以供日常使用!(这并不是一个魔术,只是为了使代码更短,更少重复,防错,更一致和可读性更高)。

    PDO也是如此!

    现在再次提出您的问题。

    但是通过使用它们是否可以消除使用mysql_real_escape_string之类的东西的需要?

    是。

    但是我认为这大致是应该从数据库中获取用户的想法。

    不是要获取,而是要向查询添加任何数据!

    如果我没记错的话,你必须在PDO:PARAM_STR之后给出一个长度

    您可以,但不必。

    现在,这一切安全吗?

    在数据库安全方面,此代码中没有弱点。没什么要固定的。

    为了确保显示安全-只需在该网站上搜索XSS关键字即可。

    希望我对此事有所了解。

    顺便说一句,对于长插入,您可以使用我有一天写的函数,使用PDO插入/更新帮助器函数

    但是,我目前不使用准备好的语句,因为我喜欢使用自制的占位符,而不要使用上面提到的库。因此,要对付下面的riha发布的代码,该代码将短于这两行:

    $sql = 'SELECT * FROM users WHERE name=?s AND type=?s AND active=?i'; $data = $db->getRow($sql,$_GET['name'],'admin',1); 但是,当然,您也可以使用准备好的语句使用相同的代码。

    • (yes I am aware of the Schiflett's scaring tales)来源:stack overflow
    2020-05-18 11:12:08
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
One Box: 解读事务与分析一体化数据库 HybridDB for MySQL 立即下载
One Box:解读事务与分析一体化数据库HybridDB for MySQL 立即下载
如何支撑HTAP场景-HybridDB for MySQL系统架构和技术演进 立即下载

相关镜像