为什么不应该使用mysql_*函数的技术原因是什么?(例如mysql_query()、mysql_connect()或mysql_real_ascape_string())?

为什么我要使用其他东西,即使它们在我的网站上工作?

如果它们在我的网站上不起作用,为什么我会出现这样的错误

警告:mysql_connect():没有这样的文件或目录


当前回答

MySQL扩展:

未积极开发自PHP 5.5(2013年6月发布)起正式弃用。自PHP 7.0(2015年12月发布)起已完全删除这意味着截至2018年12月31日,它不存在于任何支持的PHP版本中。如果您使用的是支持它的PHP版本,那么您使用的版本不会解决安全问题。缺少OO接口不支持:非阻塞异步查询准备好的语句或参数化查询存储过程多个语句交易“新”密码身份验证方法(默认情况下,在MySQL 5.6中打开;5.7中需要)MySQL 5.1或更高版本中的任何新功能

由于它已被弃用,因此使用它会使您的代码不那么经得起未来考验。

缺少对准备好的语句的支持尤为重要,因为与使用单独的函数调用手动转义外部数据相比,它们提供了一种更清晰、更不易出错的转义和引用外部数据的方法。

请参阅SQL扩展的比较。

其他回答

mysql_函数:

已过时-不再维护不允许您轻松移动到另一个数据库后端不支持准备好的语句,因此鼓励程序员使用串联来构建查询,从而导致SQL注入漏洞

易于使用

分析和综合原因已经提到。对于新手来说,停止使用过时的mysql_函数是一个更重要的激励因素。

现代数据库API更易于使用。

主要是绑定参数可以简化代码。而且有了优秀的教程(如上所述),向PDO的过渡并不太困难。

然而,一次重写更大的代码库需要时间。Raison d‘être表示此中间选项:

替代mysql的等效pdo_*函数_*

使用<pdo_mysql.php>,您可以毫不费力地切换旧的mysql_函数。它添加了pdo_函数包装器,取代了mysql_对应的包装器。

只需包含一次(“pdo_mysql.php”);在必须与数据库交互的每个调用脚本中。删除所有地方的mysql_函数前缀,并将其替换为pdo。mysql_connect()变为pdo_connect()mysql_query()变为pdo_query()mysql_num_rows()变为pdo_num_rowsmysql_insert_id()变为pdo_insert_id()mysql_fetch_array()变为pdo_fetch_arraymysql_fetch_assoc()变为pdo_fetch_assocmysql_real_ascape_string()变为pdo_real_escape_string()等等您的代码工作方式相同,但大部分看起来仍然相同:includeonce(“pdo_mysql.php”);pdo_connect(“localhost”、“usrABC”、“pw1234567”);pdo_select_db(“测试”);$result=pdo_query(“SELECT title,html FROM pages”);而($row=pdo_fetch_assoc($result)){打印“$row[title]-$row[html]”;}

等等。您的代码正在使用PDO。现在是时候真正利用它了。

绑定参数很容易使用

你只需要一个不那么笨重的API。

pdo_query()为绑定参数添加了非常简单的支持。转换旧代码很简单:

将变量移出SQL字符串。

将它们作为逗号分隔的函数参数添加到pdo_query()中。打问号?作为变量之前的占位符。去掉之前包含字符串值/变量的“单引号”。

对于较长的代码,优势变得更加明显。

字符串变量通常不只是插入到SQL中,而是与其间的转义调用连接在一起。

pdo_query("SELECT id, links, html, title, user, date FROM articles
   WHERE title='" . pdo_real_escape_string($title) . "' OR id='".
   pdo_real_escape_string($title) . "' AND user <> '" .
   pdo_real_escape_string($root) . "' ORDER BY date")

具有应用了占位符,您不必担心:

pdo_query("SELECT id, links, html, title, user, date FROM articles
   WHERE title=? OR id=? AND user<>? ORDER BY date", $title, $id, $root)

请记住,pdo_*仍然允许或。只是不要转义变量并将其绑定到同一个查询中。

占位符功能由其背后的真实PDO提供。因此也允许:稍后命名占位符列表。

更重要的是,您可以在任何查询后安全地传递$_REQUEST[]变量。当提交<form>字段与数据库结构完全匹配时,它甚至更短:

pdo_query("INSERT INTO pages VALUES (?,?,?,?,?)", $_POST);

太简单了。但是,让我们回到一些重写建议和技术原因,来解释为什么你可能想要摆脱mysql并逃离。

修复或删除任何旧的学校消毒()函数

将所有mysql_调用转换为带有绑定参数的pdo_query后,删除所有冗余的pdo_real_escape_string调用。

特别是,您应该修复任何消毒剂、清洁剂或过滤器This或clean_data函数,如过期教程以一种或另一种形式宣传的那样:

function sanitize($str) {
   return trim(strip_tags(htmlentities(pdo_real_escape_string($str))));
}

这里最明显的缺陷是缺少文档。更重要的是,过滤的顺序完全错误。

正确的顺序应该是:不赞成将stripse作为最内部的调用,然后trim,然后stripse_tags,htmlentities作为输出上下文,最后是_escape_string,因为它的应用程序应该直接在SQL中间存储之前。但作为第一步,只需去掉_real_aescape_string调用。如果您的数据库和应用程序流需要HTML上下文安全字符串,您可能需要暂时保留cleaning()函数的其余部分。添加一个注释,它以后只应用HTML转义。字符串/值处理委托给PDO及其参数化语句。如果在您的消毒功能中提到stripslases(),则可能表明存在更高级别的监督。这通常是为了消除不推荐使用的magic_quotes的损坏(双转义)。然而,最好是集中固定,而不是逐串固定。使用一种用户区反转方法。然后删除消毒功能中的stripslasshes()。magic_quotes上的历史注释。该功能被正确地弃用。然而,它通常被错误地描述为失败的安全功能。但魔法语录是一个失败的安全功能,就像网球作为营养来源失败一样。这根本不是他们的目的。PHP2/FI中最初的实现明确地引入了它,只是“引号将自动转义,从而更容易将表单数据直接传递给msql查询”。值得注意的是,与mSQL一起使用是意外安全的,因为它只支持ASCII。然后PHP3/Zend为MySQL重新引入了magic_quotes,并对其进行了错误的记录。但最初它只是一个方便的功能,并不是为了安全。

准备的报表有何不同

当您在SQL查询中加入字符串变量时,您不仅需要更复杂的操作。MySQL再次分离代码和数据也是多余的工作。

SQL注入只是当数据泄漏到代码上下文中时。数据库服务器稍后无法发现PHP最初将变量粘在查询子句之间的位置。

使用绑定参数,可以在PHP代码中分离SQL代码和SQL上下文值。但它不会在幕后再次被搅乱(除了PDO::EMULATE_PREPARES)。您的数据库接收未变化的SQL命令和1:1的变量值。

虽然这个答案强调了您应该关注删除mysql_的可读性优势。由于这种可见的技术数据/代码分离,偶尔也会有性能优势(重复的INSERT值不同)。

请注意,参数绑定仍然不是针对所有SQL注入的一站式解决方案。它处理数据/值的最常见用法。但不能白名单列名/表标识符,帮助动态子句构造,或仅列出纯数组值列表。

混合PDO使用

这些pdo_*包装器函数构成了一个编码友好的间隙API。(如果不是特殊的函数签名转换,这几乎是MYSQLI所能做到的)。他们也在大多数时候暴露真实的PDO。重写不必停止使用新的pdo_函数名。您可以逐个将每个pdo_query()转换为普通的$pdo->prepare()->execute()调用。

然而,最好从简化开始。例如,常见的结果获取:

$result = pdo_query("SELECT * FROM tbl");
while ($row = pdo_fetch_assoc($result)) {

可以用foreach迭代替换:

foreach ($result as $row) {

或者更好的是直接和完整的阵列检索:

$result->fetchAll();

在大多数情况下,您将得到比PDO或mysql_通常在查询失败后提供的警告更有用的警告。

其他选项

因此,这很有希望看到一些实际的原因和一个值得放弃mysql_的途径。

仅仅切换到pdo并不能完全解决问题。pdo_query()也只是它的前端。

除非您还引入了参数绑定,或者可以利用更好的API中的其他东西,否则这是一个毫无意义的切换。我希望它被描绘得足够简单,不会加深对新人的失望。(教育通常比禁止更好。)

虽然它符合可能工作的最简单的东西,但它仍然是非常实验性的代码。我只是周末写的。然而,有太多的选择。只需搜索PHP数据库抽象并浏览一下。一直以来都有很多优秀的图书馆可以完成这样的任务。

如果您想进一步简化数据库交互,像Paris/Inidiorm这样的映射器值得一试。就像没有人在JavaScript中使用乏味的DOM一样,现在您不必照顾原始的数据库界面。

不要使用mysql,因为不推荐使用Mysqli。

弃用的含义:

这意味着不要使用某些特定的功能/方法/软件功能/特定的软件实践,这只是意味着不应该使用它,因为该软件中有(或将有)更好的替代方案,而应该使用它。

使用不推荐使用的函数时可能会出现以下几个常见问题:

1.功能完全停止工作:应用程序或脚本可能依赖于不再支持的功能,因此使用其改进版本或替代版本。

2.显示有关弃用的警告消息:这些消息通常不会干扰站点功能。然而,在某些情况下,它们可能会中断服务器发送标头的过程。

例如:这可能会导致登录问题(cookie/会话设置不正确)或转发问题(301/302/303重定向)。

请记住:

-弃用的软件仍然是软件的一部分。

-弃用的代码只是代码的状态(标签)。

MYSQL与MYSQLI的主要区别mysql数据库*

旧数据库驱动程序MySQL只能按程序使用没有针对SQL注入攻击的保护在PHP 5.5.0中被弃用,在PHP 7中被删除

mysqli数据库

新数据库驱动程序当前正在使用准备好的语句可防止攻击

首先,让我们从我们给每个人的标准评论开始:

请不要在新代码中使用mysql_*函数。它们不再被维护,并被正式弃用。看到红盒子了吗?学习准备好的语句,并使用PDO或MySQLi-本文将帮助您决定使用哪一种。如果你选择PDO,这里有一个很好的教程。

让我们一句一句地来解释一下:

它们不再被维护,并被正式弃用这意味着PHP社区正在逐渐放弃对这些非常古老的函数的支持。它们很可能在未来(最近)版本的PHP中不存在!在不久的将来,继续使用这些函数可能会破坏代码。新!-ext/mysql从PHP 5.5开始正式被弃用!更新!ext/mysql已在PHP7中删除。相反,你应该学习准备好的陈述mysql_*扩展不支持准备好的语句,这是针对SQL注入的一种非常有效的对策。它修复了依赖MySQL的应用程序中的一个非常严重的漏洞,该漏洞允许攻击者访问您的脚本并对您的数据库执行任何可能的查询。有关更多信息,请参阅如何防止PHP中的SQL注入?看到红盒子了吗?当您转到任何mysql函数手册页面时,都会看到一个红色框,说明不应该再使用它。使用PDO或MySQLi有更好、更健壮和构建良好的替代方案,PDO-PHP数据库对象,它为数据库交互提供了完整的OOP方法,以及MySQLi,它是MySQL特有的改进。

原因有很多,但可能最重要的一点是,这些函数鼓励不安全的编程实践,因为它们不支持准备好的语句。准备好的语句有助于防止SQL注入攻击。

当使用mysql_*函数时,您必须记住通过mysql_real_aescape_string()运行用户提供的参数。如果你只在一个地方忘记了,或者你碰巧只漏掉了部分输入,你的数据库可能会受到攻击。

在PDO或mysqli中使用已准备好的语句将使其更难产生此类编程错误。