如何在PHP中将BigInt转换以防止SQL注入?

3

我正在使用 PHP 并在 MySQL 服务器上运行 SQL 查询。为了防止 SQL 注入,我正在使用 mysql_real_escape_string 函数。

对于数字转换,我也在以下方式中使用 (int):

$desired_age = 12;
$query = "select id from users where (age > ".(int)$desired_age.")";
$result = mysql_query($query);

但是,当变量包含更大的数字时,强制转换会失败,因为它们比int大。

但是,当变量包含较大的数字时,强制转换将失败,因为它们比int大。

(通俗易懂版)
$user_id = 5633847511239487;
$query = "select age from users where (id = ".(int)$user_id.")";
$result = mysql_query($query);
// this will not produce the desired result, 
// since the user_id is actually being cast to int

除了使用mysql_real_escape_string外,还有其他方法可以插入大量数字(如BIGINT),以防止SQL注入吗?


这里也有一个需要注意的地方:$user_id = 5633847511239487; 不会保存你想要的值,而且也无法将该数字转换为bigint类型。你需要将其作为字符串而不是整数来保存 - $user_id = '5633847511239487'; - nathan
不要再费心清理输入数据的麻烦了,使用参数化查询来避免 SQL 注入。http://bobby-tables.com/php.html 展示了如何在 PHP 中实现。 - Andy Lester
6个回答

11

如果您是自己生成用户ID,则无需为MySQL进行强制转换,因为不存在SQL注入或其他字符串问题的可能性。

如果它是用户提交的值,请使用filter_var()(或is_numeric())来验证它是一个数字而不是字符串。


本来也要说同样的话,类型转换很有用,但仅适用于查询字符串中的数字之类的不是用户输入结果的情况。它可以防止人们篡改查询字符串。至于用户输入,则检查值是否为数字是最佳选择,因为它允许您提供友好的消息。 - Tom Gullen

3
您可以使用类似以下的内容:

您可以使用类似以下的内容:

preg_replace('/[^0-9]/','',$user_id);

要替换字符串中的所有非数字符号。但实际上并不需要这样做,只需使用mysql_real_escape_string()函数即可,因为一旦构建$ query,您的整数值将被转换为字符串。


只是为了对比而发布这个,is_numeric也允许像“1.12”这样的浮点值,这可能不完全是yehuda想要的 :) - michael
我测试了preg_replace解决方案,并发现它仅限于14个字符。因此,我正在使用mysql_real_escape_string来处理字符串和数字用户输入。谢谢大家。 - yehuda

1

使用服务器端准备好的参数化语句(从而消除了对xyz_real_escape_string()的需要),或将id视为字符串。MySQL服务器内置了字符串<->数字转换规则,如果您决定更改id字段的类型/结构,则无需同时更改php代码。除非您有具体的(微观)优化需求,通常不需要让代码对数据库中id字段的结构和值范围做出这种假设。

$pdo = new PDO('mysql:...');
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

$stmt = $pdo->prepare('SELECT age FROM users WHERE id=?');
$stmt->execute(array('5633847511239487'));

1

验证输入。不要简单地转义,而是要验证它,如果是一个数字的话。有几个PHP函数可以完成这个任务,比如is_numeric() - 查找变量是否为数字或数值字符串

http://www.php.net/is_numeric


0
经过一些研究,我已经得出了这样的设置。
private function escapeInt($value)
{
    if (is_float($value))
    {
        return number_format($value, 0, '.', ''); // may lose precision on big numbers
    }
    elseif(preg_match('/^-?[0-9]+$/', $value))
    {
        return (string)$value;
    }
    else
    {
        $this->error("Invalid value");
    }
}

针对浮点数单独处理,因为$i = 184467440737095;在32位系统上会变成浮点数,当转换为字符串时会崩溃成科学计数法。
其余部分使用简单的正则表达式


0
你甚至可以用*1乘以變量,你可以檢查它能接受的最小值和最大值(對於年齡來說,bigint根本不是一個選項...那麼為什麼要允許超出你準備好的值的數字呢? 此外,還有PDO與其查詢準備。

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