我使用PDO访问我的MySQL数据库,并希望使用IN。但遗憾的是,它没有与prepare一起工作,所以我写了这个函数
function is_numeric_array($array){
if(!is_array($array))
return is_numeric($array);
if(is_array($array))
foreach($array as $int)
if(!is_numeric($int))
return false;
return true;
}
然后像这样使用它
if(!is_numeric_array($_SESSION['story'])){
die("Error, array contains non-integers");
}
$query = "(";
for($i = 0; $i<count($_SESSION['story']); $i++)
$query .= $_SESSION['story'][$i].(count($_SESSION['story'])-1 != $i ? "," : "");
$query .= ")";
//Collect all data needed
$stories = openConnection() -> query("SELECT * FROM `stories` WHERE `id` IN {$query}") -> fetchAll();
我知道,看起来很难看。但我不希望任何SQL注入。
答案 0 :(得分:4)
你真的不必测试输入是数字的,因为在MySQL中,任何字符串,例如数值上下文中的'123abc'
(比如与整数列id
进行比较)隐式地仅采用数字而忽略其余数字。像'abc'
这样的非数字字符串只有整数值0,因为没有前导数字。
关键是,如果使用查询参数,则SQL注入的值是安全的。输入来自$ _SESSION还是其他来源无关紧要。对于SQL注入,$ _SESSION既不安全也不安全,而是将数据传递给重要的查询。
我还会简化代码以格式化参数占位符列表:
$placeholders = implode(',', array_fill(1, count((array)$_SESSION['story']), '?'));
忘记bindParam(),只需将数组传递给execute()
。
//Collect all data needed
$storyQuery = openConnection() -> prepare("SELECT * FROM `stories`
WHERE `id` IN ({$placeholders})");
$storyQuery -> execute((array)$_SESSION['story']);
$story = $storyQuery -> fetchAll();
重新评论:
在PDO中,您可以使用:id
之类的命名参数,也可以使用位置参数,这些参数始终为?
(但不要在给定查询中混合这两种类型,请使用一个或者其他)。
将数组传递给execute()
会自动将数组元素绑定到参数。简单数组(即由整数索引)易于绑定到位置参数。
如果使用命名参数,则必须传递一个关联数组,其中数组的键与参数名称匹配。 1}}可以选择使用数组键作为前缀,但不是必需的。
如果您是PDO新手,阅读documentation真的很有意义。有代码示例和一切!
答案 1 :(得分:1)
$ _ SESSION只是一种通过会话在服务器上存储数据的方法。它与SQL注入没有直接关系。
答案 2 :(得分:-2)
出于安全考虑,即使它是cookie或会话,我存储的哈希只是字母数字。当我针对任何类型的注入/修改检查cookie /会话时,我使用ctype_alnum:
if (ctype_alnum($_SESSION['value']))
// exec code
else
// trigger_error
这样,无论是谁设置SESSION值(你或客户端,如果你给他的可能性),就不会出现像comma
这样的非字母数字字符,{{1 }},quotes
或其他任何内容。