准备用户定义的搜索词以进行查询

时间:2012-08-16 19:28:40

标签: php mysql escaping sql-injection user-input

对于搜索功能,我编写了一个由PHP脚本执行的MySQL查询。我没有进行全文搜索。相反,我正在使用以下方法进行搜索:

... WHERE field LIKE '%etc%' AND field REGEXP '[[:<:]]etc[[:>:]]'

现在,我的想法是在PHP中准备这些动态值,例如:

$word = '2*3%5_1^0'; // just an example

$wordLike = strtr($word,array('\\'=>'\\\\','%'=>'\\%','_'=>'\\_'));
// instead of my old solution:
// $wordLike = preg_replace('~([%_])~', '\\\\$1', $word);
$wordLike = $db_con->escape('%' . $wordLike . '%');

$spaces = '[[:blank:]]|[[:punct:]]|[[:space:]]';
// I'm not sure about the difference between blank & space, though

$wordRX = preg_quote($word);
$wordRX = $db_con->escape('(^|'.$spaces.')'.$wordRX.'($|'.$spaces.')');
// instead of my old solution:
// $wordRX = $db_con->escape('[[:<:]]' . $wordRX . '[[:>:]]');

然后使用这些值,如...

... WHERE field LIKE '$wordLike' AND field REGEXP '$wordRX'

,使用此示例输入,结果为

...
WHERE field LIKE '%2*3\\%5\\_1^0%' AND
field REGEXP '[[:<:]]2\\*3%5_1\\^0[[:>:]]`

几个笔记......

  • 在我的实际代码中,我正在处理多个单词,这只是伪代码。
  • 我用来搜索单词的方法 - LIKE&amp; REGEXP在一起 - 是我尝试过的方法中最快的一个。
  • 我知道我应该使用PDO,除非与我的问题相关,否则请不要输入任何内容

Q1:这是正确的方法吗? Q2:这对SQL注入是否足够安全?

<小时/>

一些其他信息

关于MySQL REGEXP ...

以下字符由preg_quote()

转义
  

即可。 \ + *? [^] $(){} =! &LT; &GT; | : -

以下是REGEXP

中[偶尔]特殊字符的列表
  

即可。 \ + *? [^] $(){} | -

REGEXP中还有其他构造,但它们都被单/双括号包围,因为我知道所有括号都会被preg_quote()转义,我觉得我不应该关心他们。

关于MySQL LIKE ...

LIKE中只有2个特殊字符是

  

_%

所以逃避它们似乎就足够了 如果我遗漏任何东西,请纠正我。

3 个答案:

答案 0 :(得分:2)

来自你提到的mysql_real_escape_string()函数的公寓应该可以很好地对SQL注入进行清理。

你必须使用适当的转义函数正确地转义任何用户输入,如果你把它描绘成处理这个用户输入的链接处理块,你将知道以哪种顺序(从最后到第一个)以及要逃避的内容/ unescape和什么时候,你应该可以确保一个干净的输入(验证是一个不同的问题)。

而且,正如您已经知道的那样,PDO上的quote()Mysqli prepare()是更好的方法。

答案 1 :(得分:1)

尝试使用mysql_real_escape_string()

$word = '2*3%5_1^0';

$query = 'SELECT * FROM TABLE_NAME WHERE field REGEXP "(.*)[[:<:]]'.mysql_real_escape_string($word).'[[:>:]](.*)" ';

答案 2 :(得分:1)

function clean($str) {
    $str = @trim($str);
    if(get_magic_quotes_gpc()) {
        $str = stripslashes($str);
    }
    return mysql_real_escape_string($str);
}

然后:

$word = clean($_POST['whatever post']);

然后修剪一下你的好消息。这个php函数做的是获取所有文字并将它们变成字符串,所以没有人可以说删除你的数据库等