如何在PHP中使用mysql_real_escape_string函数

5

在我编写的程序中,我通过表单获取用户提供的SQL查询。然后我会在我的数据库上运行该查询。

我知道不能“信任”用户输入,因此我想对输入进行消毒处理。我试图使用mysql_real_escape_string,但一直无法使其正常工作。

这是我尝试的内容,给定输入为:select * from Actor;

//"query" is the input string: 
$clean_string = mysql_real_escape_string($query, $db_connection); 
$rs = mysql_query($clean_string, $db_connection); 
if (!$rs) 
{ 
    echo "Invalid input!"; 
} 

这总是给我

"无效的输入!"

错误。

当我去掉 clean_string 部分,只运行 mysql_query 在查询上时,不会输出

"无效的输入"

消息。相反,当我这样做:

$rs = mysql_query($query, $db_connection); 
if (!$rs) 
{ 
   echo "Invalid input!"; 
} 

它不会输出

"无效的输入"。

然而,我需要使用mysql_real_escape_string函数。我做错了什么?

更新:

给定select * from Actor;作为输入,我发现以下内容。

使用echo语句,我发现在进行净化之前,字符串保留了正确的值:select * from Actor;。然而,在净化之后,它保留了错误的值select *\r\nfrom Actor;,因此出现了错误消息。为什么mysql_real_escape_string会这样做?


我不理解输入部分... 你是从用户输入中获取整个查询还是只是一些数据以后用于生成查询?我希望这不是第一种情况,否则你的安全性会有严重问题。 - Wh1T3h4Ck5
尝试一下这个教程:http://net.tutsplus.com/tutorials/php/sanitize-and-validate-data-with-php-filters/ - Ali Ben Messaoud
更改为: die('无效输入:' . mysql_error()); 以查看是否出现mysql错误。 - k to the z
你可以考虑使用带参数的预处理语句和mysqli接口来避免整个问题,这是mysql推荐的做法。 - dkretz
Wh1T3h4Ck5:我可能应该说明一下,这只是我正在学习的课程的一个小项目。确实,我正在将整个查询作为输入进行抓取。不用担心,我不会让你们帮我做作业。这个错误显然只是我的实际项目的一个小部分。 - Casey Patton
如果旧的mysql扩展是课程的一部分,那么这门课程已经非常过时了。 - outis
6个回答

13

在查询中使用它的实际值,而不是整个查询字符串本身。

例子:

$username = mysql_real_escape_string($_POST['username']);
$query = "update table set username='$username' ...";
$rs = mysql_query($query);

1

mysql_real_escape_string()是字符串转义函数。它并不会使任何输入变得安全,只能处理字符串值,并且不能用于LIKE子句,而整数仍需要以不同的方式处理。

一个更简单更通用的例子可能是:

 $post = array_map("mysql_real_escape_string", $_POST);
 // cleans all input variables at once

 mysql_query("SELECT * FROM tbl WHERE id='$post[id]' 
                OR name='$post[name]' OR mtime<'$post[mtime]' ");
 // uses escaped $post rather than the raw $_POST variables

请注意,每个变量仍必须用单引号'括起来作为SQL字符串。(否则转义将毫无意义。)

1
不要再使用过时的mysql扩展,转而使用PDO预处理语句参数不容易受到注入攻击,因为它们将值与语句分开。预处理语句和PDO还有其他优点,包括性能、易用性和附加功能。如果您需要教程,请尝试“使用PHP和PDO编写MySQL脚本”。

0

在编写查询语句时,应该使用mysql_real_escape_string来转义参数,而不是整个查询语句本身。

例如,假设您从表单中接收到两个变量。那么,您的代码应该像这样:

$Query = sprintf(
    'INSERT INTO SomeTable VALUES("%s", "%s")', 
    mysql_real_escape_string($_POST['a'], $DBConnection),
    mysql_real_escape_string($_POST['b'], $DBConnection)
);

$Result = mysql_query($Query, $DBConnection);

0

手册 mysql_real_escape_string()

转义字符串中的特殊字符,以便在SQL语句中使用

因此,您不能转义整个查询,只能转义数据...因为它将转义所有不安全的字符,例如引号(查询的有效部分)。

如果您尝试这样做(转义整个查询)

echo mysql_real_escape_string("INSERT INTO some_table VALUES ('xyz', 'abc', '123');");

输出是

INSERT INTO some_table VALUES (\'xyz\', \'abc\', \'123\');

那不再是有效的查询


0

这对我有用。dwolf (wtec.co)

<?php
// add data to db
require_once('../admin/connect.php');

$mysqli = new mysqli($servername, $username, $password, $dbname);

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$post = $mysqli->real_escape_string($_POST['name']);
$title = $mysqli->real_escape_string($_POST['message']);


/* this query with escaped $post,$title will work */
if ($mysqli->query("INSERT into press (title, post) VALUES ('$post', '$title')")) {
    printf("%d Row inserted.\n", $mysqli->affected_rows);
}

$mysqli->close();


//header("location:../admin"); 
?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接