如何使用PDO查询安全地使用$ _GET [“id”]?

时间:2014-06-27 10:37:26

标签: php mysql pdo

我正在尝试从网址获取网页的ID,并使用它从数据库中检索信息。我想确保id是一个长度小于4的整数,如果没有,则重定向到父页面。

if(isset($_GET["id"])) {
    $id = (int) $_GET["id"];
    // If id is longer than 4 redirect
    if(strlen($id) > 4) {
        header("Location: /parent.php");
        exit;
    }
    try {
        $sth = $dbh -> prepare("SELECT id, title, etc, FROM table WHERE id = :id");
        $sth -> bindParam(':id', $id, PDO::PARAM_INT);
        $sth -> execute();
    } catch(PDOException $e) {
        // print $e -> getMessage();
        echo "Error";
        exit;
    }
    $feature = $sth -> fetch(PDO::FETCH_ASSOC);
    // If query result is empty redirect
    if($feature == false) {
        header("Location: /parent.php");
        exit;
    }
    $sth = null;
} else { // If id isn't set redirect
    header("Location: /parent.php");
    exit;
}

我这样做是否安全/正确?我还在处理这类事情,所以我第二次猜测自己。

此外,它似乎按照我的意图工作,除非将id设置为123abc(child.php?id = 123abc),它将其解释为123并仍然加载id 123的信息。因为我正在投类型是它只是忽略了abc部分?我是否应该担心它仍然会加载并且不会重定向到父级?

2 个答案:

答案 0 :(得分:2)

您可以使用input filtering来确保传递的标识符确实是一个整数;它是否大于9999应该无关紧要,但也许测试一个正整数是一个好主意:

if (($id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT)) !== false && $id > 0) {
    // id was passed and it's a valid integer
} else {
    // evil request, die die
}

使用预准备语句已经减轻了潜在的SQL注入攻击,因此代码的其余部分不必更改,但我个人会尝试制作单个故障流而不是四个单独的(但几乎相同的)故障流

答案 1 :(得分:1)

是的,通过将输入转换为整数,您已经规避了任何SQL注入攻击。 通过使用绑定变量,您再次阻止了sql注入攻击。 :)

你在int上使用strlen有点难看,所以我建议检查$ id>虽然你可能不会注意到差异。