php 关于 INT 的分页安全性

php pagination security regarding INT

我希望将页面上的分页更新为 PDO。但是,我想确保它 100% 没有任何 SQL 注入等

以下是我发现的分页脚本的内容,我认为它可以正常工作。然而,因为它将从 URL 中提取数据,所以我有点担心这条线:

if (isset($_GET["page"])) { $page  = $_GET["page"]; } else { $page=1; };

我可以看到 isset 在那里检查变量是否为 NULL(我认为)但我看不到任何检查它是否不是数字。

我正在考虑更改为:

if (isset($_GET["page"])) { $page  = (int)$_GET["page"]; } else { $page=1; };

因为我认为这将检查页面变量是否为数字。或者应该是:

if (isset((int)$_GET["page"])) { $page  = $_GET["page"]; } else { $page=1; };

还是两者都使用 INT?我认为在旧的 mysql 中,您会使用 striptags 等,但不确定是否使用 PDO(仍在学习)。

这是上述改动前的完整代码。

<?php
        include('connect.php');
        if (isset($_GET["page"])) { $page  = $_GET["page"]; } else { $page=1; };
        $start_from = ($page-1) * 3;        
        $result = $db->prepare("SELECT * FROM members ORDER BY id ASC LIMIT $start_from, 3");
        $result->execute();
        for($i=0; $row = $result->fetch(); $i++){
    ?>
    <tr class="record">
        <td><?php echo $row['a']; ?></td>
        <td><?php echo $row['b']; ?></td>
        <td><?php echo $row['c']; ?></td>
    </tr>
    <?php
        }
    ?>
</tbody>
</table>
<div id="pagination">
    <?php 

    $result = $db->prepare("SELECT COUNT(id) FROM members");
    $result->execute(); 
    $row = $result->fetch(); 
    $total_records = $row[0]; 
    $total_pages = ceil($total_records / 3); 

    for ($i=1; $i<=$total_pages; $i++) { 
                echo "<a href='index.php?page=".$i."'";
                if($page==$i)
                {
                echo "id=active";
                }
                echo ">";
                echo "".$i."</a> "; 
    }; 
    ?>

Connect.php 包含

$db = new PDO('mysql:host='.$db_host.';dbname='.$db_database, $db_user, $db_pass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

如有任何帮助或指导,我们将不胜感激。另外,如果您能发现其他安全方面的问题,请告诉我。

编辑:

添加行:

$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

到connect.php

还有其他安全提示吗?

使用参数化查询这将避免注入的可能性。要使用 PDO 做到这一点,您可以

  1. 将用户提供的值传递到数组中执行
  2. 放置一个问号作为占位符来代替用户数据
$result = $db->prepare("SELECT * FROM members ORDER BY id ASC LIMIT ?, 3");
$result->execute(array((int)$start_from));

你也可以绑定,http://php.net/manual/en/pdostatement.bindparam.php(基于doc和其他线程,我一般不绑定)。

$result = $db->prepare("SELECT * FROM members ORDER BY id ASC LIMIT :start, 3");
$result->bindParam(':start', (int)$start_from, PDO::PARAM_INT);
$result->execute();

这里有一个更长的线程,How can I prevent SQL injection in PHP?

还有 PHP 注释,http://php.net/manual/en/pdo.prepared-statements.php

对于更长的样本,如果您有多个值:

$result = $db->prepare("SELECT * FROM members where username = ? and email = ? ORDER BY id ASC LIMIT ?, 3");
$result->execute(array($_GET['name'], $_GET['email'], $start_from));