我有一个简单的网站,我使用PDO建立与Mysql服务器的连接。
$dbh = new PDO('mysql:host=localhost;dbname=DB;port=3306', 'USER',
'SECRET',array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
我的网站上有一些流量,并且达到了服务器连接限制,并且网站引发了此错误,其中包含我的PLAIN密码!
致命错误:未捕获的异常 带有消息的'PDOException' 'SQLSTATE [08004] [1040]太多了 连接' /home/domain/html/index.php:xxx 堆栈跟踪:#0 /home/domain/html/index.php(64): PDO-> __构建体( 'MySQL的:主机=轨迹...', 'USER','SECRET',Array)#1 抛出了{main} /home/domain/html/index.php on 第64行
具有讽刺意味的是,我出于安全原因切换到了PDO,所以这让我很震惊,因为这个确切的错误是你可以在大多数使用简单的http泛滥的网站上轻易引起的。
我现在已将我的连接包装在try / catch块中,但我认为这仍然是灾难性的!
我是PDO的新手,所以我的问题是:为了安全,我该怎么做?如何以安全的方式建立连接?是否还有其他已知的安全漏洞,我必须注意这个漏洞?
答案 0 :(得分:20)
无论如何,您的PHP.ini应该有display_errors = off
以避免此问题。除了PDO之外,揭示这些细节的错误来自许多地方。
是的,您还应该在try / catch块中使用它。
您也可以$pdo->setAttribute(PDO::ERRMODE_SILENT)
,但是您需要手动检查错误代码,而不是使用try / catch块。有关更多错误常量,请参阅http://php.net/manual/en/pdo.setattribute.php。
答案 1 :(得分:14)
简单的解决方法是捕获PDO构造函数抛出的PDOException:
try {
$dbh = new PDO('mysql:host=localhost;dbname=DB;port=3306', 'USER',
'SECRET',array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
} catch (PDOException $e) {
throw new Exception($e->getMessage());
}
答案 2 :(得分:7)
好的,这让我有点傻笑,错误报告的使用是出于调试目的,它可以让你快速找到并解决问题。
当您处于实时环境中时,您的服务器应仅配置为内部日志记录,而不是直接输出,因此基本上您需要关闭php.ini
中的错误输出。
display_errors = Off
但是当你在测试环境中时,这个堆栈只是一个可以帮助你的工具,并且是可配置的。
如果在实时环境中发生错误,则会记录这些错误,因此您应始终检查日志文件,然后进行相应的修复。
人们可能会指定您可以管理PHP应用程序中的错误,但是根据个人喜好,我认为这是错误的方法,为您的Web服务器和MySQL / MsSQL配置INI和配置文件将导致更多急性管理。
如果您的应用程序是公共应用程序,那么处理应用程序内的错误也是一个好主意,因为大部分客户端可能在共享主机上,并且无法完全访问服务器配置。
答案 3 :(得分:2)
我们使用编码的用户名和密码,并解码PDO构造函数中的那些,然后我们捕获PDOException并抛出一个新的PDOException,其旧的异常是它的消息,这样跟踪将只显示编码的用户名和密码。
PHP的一个很好的加密库是:defuse / php-encryption
https://github.com/defuse/php-encryption
示例代码:
<?php
class myPDOWrapper extends PDO
{
public function __construct(string $dns, string $encodedUser, string $encodedPassword)
{
try {
parent::__construct($dns, $this->decodeFunction($encodedUser), $this->decodeFunction($encodedPassword),
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]
);
}
catch (PDOException $exception) {
throw new PDOException($exception->getMessage());
}
}
private function decodeFunction(string $encoded): string
{
return \Defuse\Crypto\Crypto::decrypt($encoded, $this->decodeKey());
}
private function decodeKey(): \Defuse\Crypto\Key
{
static $key = null;
if(null === $key) {
$key = \Defuse\Crypto\Key::loadFromAsciiSafeString(getenv('MY_PDO_DECODE_KEY'));
}
return $key;
}
}