1

我需要通过 URL 为我的 MySQL 查询传递特殊符号。例如,我需要一个类似于以下内容的 URL:

www.example.com/index.php?q=AND name LIKE '%hi%'

当我第一次尝试时,我收到了 406 错误。我查了一下,显然我必须使用urlencode()and urldecode()。我把它们放进去, 406 错误消失了,但后来我得到了一个 MySQL 错误:

mysql_fetch_array(): supplied argument is not a valid MySQL result resource

通常当我得到这些时,这意味着查询没有正确编写。所以我回应了 MySQL 查询,一切看起来都很好。我什urldecode()至将我想要传递给页面的内容删除并硬编码到一个变量中,然后 MySQL 错误就消失了。但是,使用urldecode()和不使用的两个查询完全相同,所以我有点困惑。

我进入了 php.net 文档页面urldecode(),并且有一个警告说使用_GETand urldecode()together 可能会导致意想不到的事情,并且_GET已经起到解码器的作用(或者至少这是我解释措辞的方式),所以我删除urldecode()但仍留在 中_GET,导致文本未被解码,所以我想我没有正确解释文档。

urldecode()兼容 MySQL 查询?我相当肯定这是编码/解码的问题,因为我已经使用绕过编码/解码的硬编码信息测试了我的代码,并且工作正常。也许urldecode()是以某种方式将字符变成看起来相同但内部不同的特殊字符,因此 MySQL 无法读取它们?

4

3 回答 3

75

不要这样做。这是错的。当然,任何人都可以使用 a 结束查询;并开始一个新查询,删除所有内容或读出用户和密码。

一种简单且更好的方法是www.example.com/index.php?q=hi用作您的 URL,然后在服务器上(假设是 PHP)

$queryString = mysql_real_escape_string($_GET['q']);

$query = "AND name LIKE '%$queryString%'";

// Then replace $query for whatever you were using $_GET['q'] for before.
// Feel free to rename my variables what you like!

这样,用户就不会搞砸了,而且 URL 看起来更干净。mysql_real_escape_string 函数通过转义使字符串在查询中安全使用。阅读http://php.net/manual/en/function.mysql-real-escape-string.php了解更多信息。

如果您仍然不相信这很有用,请考虑如果有人发布了一个会删除您的表格的链接,然后 Google 每周抓取一次会发生什么情况。只要 Google 碰巧经过,您的数据就会被删除。

一旦您对这项技术感到满意,请阅读mod_rewrite(如果使用 Apache)以进一步清理 URL、mysqli以及它如何是 mysql 函数的改进版本,最后阅读有助于清理的PHP 数据对象(PDO) PHP 起来就更厉害了。

于 2012-07-18T18:10:16.000 回答
8

Rich 有正确的总体思路,但比引用更好的是使用数据库参数。它本质上是在您的 SQL 查询中放置一个“变量标记”,然后单独传递变量。查询最终看起来像这样:

SELECT ID, VALUE1, VALUE2
FROM MY_TABLE
WHERE VALUE3 = :param

然后在您的代码中,添加一个值来替换 for :param,然后将其与 SQL 一起发送到数据库。(在某些数据库库中,您会使用 ? 而不是 :parametername。)它比引用更好,原因有以下三个:

首先,您可以保持查询字符串不变,而不必每次都重新构建它,从而提高服务器的性能。

其次,如果您使用多个不同的参数多次向数据库发送相同的常量查询,数据库引擎可以缓存查询计划,从而提高数据库的性能。

第三,当您习惯于以参数化样式编写查询时,这会变得很自然,特别是如果您使用将参数列表作为参数的查询函数,因此很难出错。相比之下,很容易忘记引用某些内容,然后您不小心在程序中打开了一个安全漏洞。

参数化的具体工作方式取决于您使用的数据库和数据库访问库,但每个 SQL 数据库都支持它们。你应该看看它是如何为你正在使用的系统完成的。这确实是使用 SQL 的最佳方式,尤其是当您的输入来自 Internet 等不受信任的来源时。

于 2012-07-19T17:26:51.593 回答
0

mysql_query()在调用之后和调用之前的某个时间点,mysql_fetch_array()您应该检查查询是否返回 false,mysql_error()如果返回则打印。例如:

$result = mysql_query($query);
if (!$result) {
   die(htmlenitites(mysql_error())." when running <pre>".htmlenitites($query)."</pre>");
}

但:

  1. 你不应该使用 php 的 mysql 函数,你应该使用 PDO,你应该使用准备好的/参数化的查询。
  2. 除非您真的信任客户端可能键入的任何内容,否则您不应该让 SQL 从客户端传递 - 例如,这是用于后端管理界面,即使那样,除非您真的需要它,否则这可能是不好的做法(就像您是编写 phpMySQLAdmin)
于 2012-07-23T09:27:09.073 回答