如何使这个PHP代码段访问SQL安全


How can I make this PHP snippet accessing SQL secure?

问题

我现在正在建立一个网站,上面有下面的片段。我知道由于SQL注入等原因,它不安全,但解决这个问题的正确方法是什么?我看到相关的问题问了同样的问题,但MySQL,为此有PDO,但PDO_OCI是实验性的,所以我不想使用它。

我还有什么其他选择?我是否只是创建一个函数来剥离某些字符并将其包裹在$_POST上,类似于str_replace(';', '', $_POST['username']);

下面的代码片段是网站中唯一一个在查询中实际接受用户输入$_POST的部分,所以我只需要确保我得到了正确的以下内容。

代码

<?php
if (!empty($_POST)) {
  $stid = oci_parse($conn, "SELECT CustomerNo FROM Customers WHERE Username = '" . $_POST['username'] . "' AND Password = '" . $_POST['password'] . "'");
  oci_execute($stid);
  $row = oci_fetch_array($stid, OCI_NUM);
  if (!empty($row['0'])) {
    session_start();
    $_SESSION['customer'] = $row['0'];
    $_SESSION['username'] = $_POST['username'];
  }
  oci_free_statement($stid);
  oci_close($conn);
}
?>

在谷歌上快速搜索"php-oci parameter"得到了oci_bind_by_name函数,该函数看起来可以用于创建参数化查询(即the Right Way™(。

根据该页面上的示例推断,您很可能会将代码更改为以下内容(未经测试,但很可能是正确的(:

<?php
if (!empty($_POST)) {
  $stid = oci_parse($conn, 'SELECT CustomerNo FROM Customers WHERE Username = :username AND Password = :password');
  oci_bind_by_name($stid, ':username', $_POST['username']);
  oci_bind_by_name($stid, ':password', $_POST['password']);
  oci_execute($stid);
  $row = oci_fetch_array($stid, OCI_NUM);
  if (!empty($row['0'])) {
    session_start();
    $_SESSION['customer'] = $row['0'];
    $_SESSION['username'] = $_POST['username'];
  }
  oci_free_statement($stid);
  oci_close($conn);
}
?>

这样,您的用户输入就永远不会与SQL语句混合在一起。哦,我真的希望密码不是像看起来那样的纯文本…:'-(