简体   繁体   English

如何验证整数值以避免SQL注入?

[英]How to validate integer values to avoid SQL injection?

The best way to avoid SQL injection for defined value type such as numbers, is to validate the value; 避免对诸如数字之类的已定义值类型进行SQL注入的最佳方法是验证值。 since it is easier to do so comparing with mysqli preparation. 因为与mysqli准备相比,这样做更容易。 In PHP, we can do this by. 在PHP中,我们可以这样做。

1. if(!is_numeric($value)) {$value=0;}
2. $value=floatval($value);
3. $value=intval($value);
4. $value=$value * 1;

What is the most reliable one? 什么是最可靠的? or a better idea? 还是更好的主意?

UPDATE: Although I have stated in the original question, most of folks emphasized the usefulness of parameterized queries. 更新:尽管我在最初的问题中已经说过,但是大多数人都强调了参数化查询的有用性。 Definitely, it is the most efficient way to avoid SQL injection. 无疑,这是避免SQL注入的最有效方法。 But when we can simply validate an integer numeric value; 但是当我们可以简单地验证整数数值时; IMHO, there is no need to parametrization. 恕我直言,无需参数化。

For integers and floats you can use this if you don't want to do a parameterised query. 对于整数和浮点数,如果不想执行参数化查询,则可以使用它。

$clean_number = (int)$value;

$clean_number = (float)$value;

These are actually casting the value as int and float , this is faster than intval() and floatval() for example because it does not suffer the function overhead. 这些实际上将值转换为intfloat ,这比intval()floatval()更快,例如,因为它不会遭受函数开销。

I prefer to use the filter extension : 我更喜欢使用过滤器扩展名

$id = filter_var($id, FILTER_SANITIZE_NUMBER_INT);

You should definitively go for parameterized queries. 您应该明确地进行参数化查询。

You can use intval() to coerce a value to integer. 您可以使用intval()将值强制转换为整数。 The most reliable way to avoid SQL injection is to use parameterised queries. 避免SQL注入的最可靠方法是使用参数化查询。

$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'dbuser';
$password = 'dbpass';

try {
    $dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

$sth = $dbh->prepare('SELECT * FROM table WHERE id = :id');
$sth->bindParam(':id', $id, PDO::PARAM_INT); 
$sth->execute();
$result = $sth->fetchAll(PDO::FETCH_ASSOC);

If you want a seasoned advise, you have to change your mind. 如果您需要经验丰富的建议,则必须改变主意。 Completely. 完全可以

The thing that being your main concern, in fact, is the most negligible thing in the world. 实际上,您最关心的事情是世界上最微不足道的事情。 You may use one way or another with not a slightest difference. 您可以使用一种或另一种方式,但不会有丝毫差别。 There is no "most reliable" way. 没有“最可靠”的方式。 That's just several ways of doing the same. 那只是做相同事情的几种方法。

On the other hand, "there is no need to parametrization" is a grave delusion. 另一方面,“无需参数化”是一种严重的幻想。
Parameterized queries can do any good only if used explicitly, throughout whole site, with no exceptions. 参数化查询只有在整个站点中明确使用且无例外的情况下,才能发挥任何作用。 One exception can spoil all the defense. 一种例外会破坏所有防御能力。

Not to mention that parameterized query can make your life much, much easier. 更不用说参数化查询可以使您的生活变得轻松得多。
Prepared statements are not such an ugly code that propagated on this site by some enthusiasts. 准备好的语句并不是某些发烧友在此站点上传播的丑陋代码。 It's actually quick and neat way of writing safe code. 实际上,这是编写安全代码的快速而简洁的方法。
Say, the code that took cetver a dozen lines can be done in just one : 我说,那把cetver十几行代码就可以在短短的一个来完成:

$data = $db->getAll("SELECT * FROM table WHERE id = :placeholder:",$id);

and be perfectly safe 并绝对安全
without ugly manual binding. 没有难看的手动装订。
without error-prone manual casting. 没有容易出错的手动投放。

Another example to show you the power of placeholders 另一个向您展示占位符功能的示例

$sql = "SELECT * FROM table WHERE tstamp BETWEEN ?i AND ?i AND flag=?s AND IN in (?a)";
$data = $db->getAll($sql,$min,$max,$flag,$array_of_ids);

Two lines. 两行。

I am not too good with PDO but it would be like a dozen lines of code even without connect 我对PDO不太满意,但是即使没有连接也要十几行代码

$in  = implode(',', array_fill(0, count($array_of_ids), '?'));
$sql = "SELECT * FROM table WHERE tstamp BETWEEN ? AND ? AND flag=? AND id IN ($in)"
$sth = $dbh->prepare($sql);
$stmt->bindValue(1, $min);
$stmt->bindValue(2, $max);
$stmt->bindValue(3, $flag);
foreach ($array_of_ids as $i => $id) {
  $stmt->bindValue(($i+4), $id);
}
$sth->execute();
$result = $sth->fetchAll(PDO::FETCH_ASSOC);

And comparable amount with your current manual casting. 与您当前的手工铸造相当。

This is actually the power of programming. 这实际上是编程的力量
One can write a program to do all the dirty job for them. 可以编写一个程序来为他们做所有肮脏的工作。
An approach almost never seen on this site. 在该站点上几乎从未见过的方法。

Sapienti sat 智人坐

您可以使用mysql_real_escape_string()这个函数来分隔特殊字符,但是您可以做的很好以保护sqli攻击。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM