从关于intertubes的教程中我学到了一些关于做PDO查询的知识。本教程使用了try / catch,查询的结构基本如下:
try {
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $user, $pass);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $dbh->prepare("UPDATE users yada yada yadda");
$stmt->bindParam(':param1', $param1, PDO::PARAM_INT);
$stmt->bindParam(':param2', $param2, PDO::PARAM_INT);
$stmt->execute();
}
catch(PDOException $e)
{
echo $e->getMessage();
}
这当然是屏幕上的echos mysql错误。并不是说我打算进行错误的查询,但我不喜欢在屏幕上回显错误的想法,想知道如果攻击者试图引发错误并尝试从中学习一些东西会怎样。
有没有更好的方法来做到这一点,以便任何错误转到日志文件,或者实际上我没有什么可担心的,因为绑定参数消除了任何SQL注入的风险?
答案 0 :(得分:4)
本教程是正确的,因为您希望使用try..catch块来捕获可能导致错误的代码并降低您正在加载的内容。因此,如果您有一些依赖于此代码执行的代码,您希望将其包含在您的try部分中。如果您绝对需要此代码来执行您正在创建的任何工作,那么您可能希望捕获错误并将用户重定向到某种类型的错误页面。
如果您使用the php error log function,而不是
echo $e->getMessage();
您可以使用
error_log($e->getMessage(),0);
将错误消息从PDO直接发送到您的php错误日志。如果您不知道错误日志的位置,you can check out this link如果您正在运行* nix系统,则会指向它。如果您正在运行Windows,那么应该有一个配置文件可以告诉您。或者你可以检查php ini文件中它指向的位置,以便找到日志。
答案 1 :(得分:1)
有更好的方法吗
是的,当然!
这显然是处理本教程教你的PDO错误的错误方法
所以,只需摆脱这些try..catch
命令 - 就是这样。
这样您就可以像处理其他PHP错误一样处理PDO异常。因此,在查询错误的情况下,您的脚本将被暂停并且将记录错误(如果您这样告诉PHP)
要告诉PHP,你必须将log_errors
ini指令设置为1
要告诉PHP不要在屏幕上显示错误,请将display_errors
ini指令设置为0
(在开发服务器上,您可能希望将其反转)
答案 2 :(得分:0)
好吧,我的回答可能不是最佳做法,所以请将它留给最后一个选项。但就我而言,它完美无缺。
无论你在PDO :: ATTR_ERRMODE中设置什么,PDO :: __ construct都会给你一个例外。我不知道他们为什么设计它表现得那样。
我解决这个问题的方法是创建一个代码区域,我将其命名为Debug Critical Section(意味着您需要非常小心该部分中的代码),本节中的任何错误都不会直接输出给用户。
以下是我为我的框架制作的代码:
private function doPDOConnect($dbIndex, &$DBInfo, &$error) {
$dbh = null;
$successed = false;
if (!isset($this->connectedDB[$dbIndex])) {
// Enter Critical Section so no error below belowing code will cause error output, but the error still in log though
facula::core('debug')->criticalSection(true);
try {
$dbh = new PDO($DBInfo['Driver'] . ':' . $DBInfo['Connection'] . '=' . $DBInfo['Host'] . ';dbname=' . $DBInfo['Database'], $DBInfo['Username'], $DBInfo['Password'], array( PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING, PDO::ATTR_TIMEOUT => $DBInfo['Timeout'] )); // ATTR_ERRMODE => PDO::ERRMODE_WARNING. or we will cannot get anything even error happens
$dbh->facula_prefix = $DBInfo['Prefix'];
$dbh->facula_index = $dbIndex;
$dbh->facula_connection = $DBInfo; // In order you want to reconnect this specify database after connection lost etc, remove if you worry about the security issue.
$successed = true;
} catch (PDOException $e) {
$error = $e->getMessage(); // If any error, catch it, to &$error.
}
// Exit Critical Section, restore error caught
facula::core('debug')->criticalSection(false);
if ($successed) {
return $this->connectedDB[$dbIndex] = $dbh;
}
} else {
return $this->connectedDB[$dbIndex];
}
return false;
}
因此,在您的情况下,您可以将我的facula :: core('debug') - > criticalSection替换为display_errors off / on以正确处理错误显示处理程序。
例如:
$display_error_status = ini_get('display_errors');
function criticalSection($entered) {
global $display_error_status;
if ($entered) {
ini_set('display_errors', '0');
} else {
ini_set('display_errors', $display_error_status);
}
}