【问题标题】:Uncaught PDOException reveals username and password未捕获的 PDOException 显示用户名和密码
【发布时间】:2014-05-09 17:56:58
【问题描述】:
try {
    self::$dbinstance = new PDO(
        "mysql:host=$c[host];dbname=$c[dbname]", $c['user'], $c['password']
    );

    self::$dbinstance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} 
catch(PDOException $e) {
    echo "Errors" . $e->getMessage();
}

在上面的代码中,如果 PDO 无法连接到主机,fatal error 会显示用户名和密码。

Uncaught exception 'PDOException' with message 'SQLSTATE[HY000] [2003]
Can't connect to MySQL server on '172.25.102.65' (10060)' in
D:\xampp\htdocs\mytest\wh_client_2.1\classes\importmodule-class.php:33 Stack trace: #0
D:\xampp\htdocs\mytest\wh_client_2.1\classes\importmodule-class.php(33): PDO-
>__construct('mysql:host=172....', 'host', 'password') #1

一种可能的方法是在php.ini 中关闭display_error=0,但这样我就无法知道我的主机何时没有响应。

有没有办法修改错误信息?

【问题讨论】:

  • 您不应该在生产环境中显示错误。您应该抑制和/或捕获错误,并在有任何情况时向自己发送警报。
  • // self::$dbinstance->setAttribute(PDO::ATTR_ERRMODE....
  • @tympaniplayer 我怎么能抛出,因为它是一个未被捕获的异常并且它没有在 catch 块中被捕获
  • 通常我会同意@YourCommonSense,但它正在折腾用户名和密码。这不是问题吗?
  • 先告诉我,你了解堆栈跟踪的重要性吗?或者你处理错误的所有想法就像 echo "Errors".$e->getMessage();?

标签: php pdo


【解决方案1】:

,不要尝试throw 异常,因为它会吐出如此重要的信息...用一些适当的自定义错误消息处理它们,并在自定义日志记录函数中处理这些异常...

你一定在做类似的事情......

<?php

try {    
    $db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'uname', 'pass');
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $db->query('bla bla bla bla'); //<---- This will definitely fail!!!!
} catch(PDOException $ex) {
    echo "An error occurred!";
    file_put_contents('somefile.txt', $ex->getMessage(), FILE_APPEND);
}

如您所见,上述查询确实会失败。因此最终用户只会看到 An error occurred! 消息,但该错误将记录到您的 somefile.txt 文件中。

【讨论】:

  • 我已经尝试了所有方法但自动显示错误
  • 请先试试上面的东西。 custom_logging_function 你需要在你的代码上定义..就像写一些文本文件一样。
  • 即使使用custom_logging_function 脚本也会显示致命错误并忽略“发生错误”
  • @ShankarDamodaran 我有超过 50 个使用此 pdo 连接的查询,根据您的解决方案,我必须在每个查询周围放置 try & catch?
  • 亲爱的,我已经提到即使删除 throw new $e.. 也无济于事。我也编辑了问题
【解决方案2】:

你可以这样做:

<?php
// connect
try
{
    $dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
}
catch (PDOException $e)
{
    $dbh = NULL;
}

// check if connected
if($dbh)
{
    // run queries
}
else
{
    die('Oops! Our server has encountered an error, please try again later');
}
?>

【讨论】:

  • 这是一个未捕获的异常,所以它不会进入 catch 块,这是主要问题
  • 究竟是什么导致它失败?错误的凭据?错误的数据库名称?错误的主机?错误的数据库驱动程序?这段代码完美地为我工作,所以我想知道如何让它失败。
  • 做这样的事情是一种死罪。 Empty catch 就是他和@一样。
  • 我有远程主机,此时无法访问,当我看到密码和用户名在错误中可见时,这种不可用性提醒我。这就是我在这里的原因
  • 我了解:echo "Errors".$e-&gt;getMessage(); 是您的问题,因此您需要将其删除并替换为用户友好的解决方案
【解决方案3】:

错误处理和错误报告是有区别的。

  • 错误处理是防止最终用户看到任何堆栈跟踪、重要信息或自动生成的错误消息的过程。它还可以通过使用 try catch 块来修改脚本的运行方式。
  • 错误报告定义给定脚本将报告哪些信息。

为了正确处理错误,我认为ini_set('display_errors',0); 是更好的方法。您不希望屏幕上显示任何错误消息。

但是,我想获得所有可能的错误信息,所以我使用error_reporting(E_ALL);

错误写在一个文件error_log 中,它通常与您的index.php(或任何直接调用的PHP 文件)位于同一级别。您也可以从您的 cPanel 访问它。


您的错误可能未被捕获,因为您的代码位于命名空间中,而您想捕获全局命名空间PDOException。使用\ 表示您正在寻找全局PDOException 的脚本。发现错误后,您可以使用PDOException class 的常规方法回显您想要的内容。

try {
    $db = new PDO (/*connection infos*/);
}
catch (\PDOException $e) {
    switch ($e->errorCode()) {
        case 'HY000':
        // Or whatever error you are looking for
        // here it's the general error code
            mail('your@email.com','connection problem',$e->getTraceAsString());
            $db = new PDO (/*rollback connection infos of a local database*/);
            break;
    }
}

这会向您发送一封邮件,其中包含错误的踪迹,防止您的用户在告诉您有问题时看到它。

这里是the reference PDO 语句返回的错误代码。

【讨论】:

  • 这是一个很好的答案(甚至是优秀的答案),但仅限于实际实施。此外,它忽略了问题的重点,即:他的错误是未捕获。如果它们都不起作用,那么对错误处理和捕获的任何咆哮都是没有意义的。为了帮助您正确处理,让我向您提示可怜的 OP 正在寻找的两件事:1. 命名空间。 2. 可以以array的形式获取trace。并手动创建他们想要的任何输出,包括他们想要的任何数据。
  • 另外,如果您向 OP 解释堆栈跟踪的重要性,那就太好了,这在任何比通常的一页意大利面条稍微复杂一点的应用程序中都是绝对不可缺少的。
  • 使用register_shutdown_function 帮助指导通过stackoverflow.com/questions/277224/…。因为你有最相关的信息,所以我会接受作为答案
  • 现在您要将数据库凭据通过电子邮件发送给自己。这比将它们写入日志文件更糟糕 ?
  • @Pieterjan 你误会了。这是一个通用的解决方案,而不仅仅是密码大小写。在答案的第一部分中,我谈到在 screen 上看不到密码(您刚刚在方程式中添加了日志),在第二部分中,我公开了捕获异常的一般工作原理。在邮件中发送密码比在屏幕上公开要好,是的,但是那里可能有任何类型的异常处理,包括写入日志。
【解决方案4】:

当您的主机没有响应时,您会知道 - 您的主机将停止响应。然后您必须查看错误日志并找到带有特定错误的错误消息。

所以,请继续使用display_errors=0,因为它在生产环境中是必备

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-26
    相关资源
    最近更新 更多