关于INT的php分页安全性

时间:2015-05-29 15:56:35

标签: php pdo pagination

我希望将页面上的分页更新为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);

连接.php

还有其他任何安全提示吗?

1 个答案:

答案 0 :(得分:0)

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

  1. 将用户提供的值传递给数组中的execute
  2. 将问号作为占位符代替用户数据
  3. $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));