Как привести Bigint для предотвращения инъекций SQL в PHP?
Я использую php и запускаю sql запросы на сервере mysql. чтобы предотвратить инъекции sql, я использую mysql_real_escape_string.
я также использую (int) для приведения чисел, следующим образом:
$desired_age = 12;
$query = "select id from users where (age > ".(int)$desired_age.")";
$result = mysql_query($query);
эта работа.
Но когда переменная содержит большие числа, приведение их завершается неудачно, так как они больше, чем 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
Есть ли другой способ приведения большого числа (например, BIGINT), кроме использования mysql_real_escape_string, когда речь идет о предотвращении инъекций sql?
6 ответов
Вы можете использовать что-то вроде:
preg_replace('/[^0-9]/','',$user_id);
заменить все нечисловые символы в вашей строке. Но на самом деле в этом нет необходимости, просто используйте mysql_real_escape_string(), так как ваше целочисленное значение в любом случае будет преобразовано в строку после построения $query.
Если вы генерируете идентификатор пользователя самостоятельно, нет необходимости приводить его к MySQL, поскольку нет шансов на внедрение SQL или другие строковые проблемы.
Если это пользовательское значение, используйте filter_var()
(или же is_numeric()
) чтобы убедиться, что это число, а не строка.
Подтвердите ввод. Не просто избежать этого, подтвердить его, если это число. Есть пара функций PHP, которые делают свое дело, например is_numeric() - Находит, является ли переменная числом или числовой строкой
Используйте подготовленные параметризованные операторы на стороне сервера (и, таким образом, устраните необходимость в xyz_real_escape_string()) и / или рассматривайте идентификатор как строку. Сервер 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
, вы можете проверить минимальные и максимальные значения, которые вы можете принять (для возраста bigint это не вариант вообще... так зачем даже разрешать числа, превышающие значения, к которым вы подготовлены? И есть также PDO с его подготовкой запроса.
После некоторых исследований я пришел к такой установке
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-битной системе и, таким образом, рушится в научную нотацию, когда приводится в строку.
И простое регулярное выражение для отдыха