【发布时间】:2018-11-22 17:29:48
【问题描述】:
在我正在编写的 PHP 应用程序中,我不想将生产数据库凭据暴露给其他开发人员。
我在这里阅读了几个关于 SO 的问题和答案,例如以下线程对该主题有许多有趣的想法:
How to secure database passwords in PHP?
我决定将凭据移到应用程序根目录之外的文件中。 假设我正在使用 PDO,并且在我的应用程序容器中创建了我的 PDO 实例:
<?php
// ...
require_once __DIR__ . '/../db_pdo_outside_document_root.php';
$containerConfig = [
'db_connection' => function() {
return new PDO(DB_PDO_DSN, DB_PDO_USER, DB_PDO_PASSWD, DB_PDO_OPTIONS);
}
];
$appContainer = new ApplicationContainer($containerConfig);
// Use the container and handle the request...
传递给 PDO 构造函数的DB_PDO_* 常量都来自文档根目录之外的文件db_pdo_outside_document_root.php:
<?php
// db_pdo_outside_document_root.php
define('DB_PDO_DSN', 'mysql:host=localhost;dbname=app_database');
define('DB_PDO_USER', 'db_user');
define('DB_PDO_PASSWD', 'db_fancy_passwd');
define('DB_PDO_OPTIONS', [
PDO::ATTR_PERSISTENT => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
到目前为止,一切都很好。然而,这并没有多大帮助,因为如果有人想回显常量的内容,他们可以轻松做到:
<?php
// In some PHP file used by the application...
echo DB_PDO_PASSWD; // echoes the DB password.
//mail('developer@mail.com', 'Subject', DB_PDO_PASSWD); // Or send it by email
现在,当然,您必须信任与您共事的同事,但谁知道呢,有时会发生员工离职、可能被解雇等情况。而且我们不希望他们有机会以某种方式将生产数据库凭据存储在他们的计算机上。
所以我想也许不是在文件中定义常量,而是文件本身可以返回 PDO 对象,这反过来似乎不会暴露它用来连接数据库的凭据:
<?php
// ...
var_dump($appContainer->get('db_connection'))
输出类似:
/path/to/htdocs/file.php:4:
object(PDO)[13]
所以我最终会在我的应用程序的引导代码中得到类似的东西:
<?php
// ...
$containerConfig = [
'db_connection' => function() {
return require_once __DIR__ . '/../db_pdo_outside_document_root.php';
}
];
$appContainer = new ApplicationContainer($containerConfig);
// Use the container and handle the request...
在外部文件中:
<?php
// db_pdo_outside_document_root.php
return new PDO('mysql:host=localhost;dbname=app_database',
'db_user', 'db_fancy_passwd', [
PDO::ATTR_PERSISTENT => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);;
但我不知道这是否足够,或者是否有一些我应该注意的警告(除了这个“解决方法”有点丑陋的事实)。
你认为其他开发人员能够以某种方式从$appContainer->get('db_connection') 的返回值中读取凭据吗(假设它返回上面的 PDO 对象)?
我也尝试了ReflectionClass,但我没有看到该对象的任何属性:
<?php
//...
$ref = new ReflectionClass($appContainer->get('db_connection'));
var_dump($ref->getProperties());
输出:
/path/to/htdocs/file.php:4:
array (size=0)
empty
您如何看待这种方法?不是本世纪的发明,但它似乎完成了这项工作。或者,也许还有一种方法可以访问我不知道的应用程序代码中的凭据。
我想听听你的意见。
感谢您的关注。
EDI:正如@IsThisJavascript 指出的那样,应用程序的代码当然仍然可以获取文件的内容并因此访问凭据,因此我的整个推理不正确,因为它没有考虑这种非常简单的情况。 我想我必须找到另一种策略,如果存在的话......
【问题讨论】:
-
maybe there is still a way to access the credentials in the application's code I am not aware of.如果他们可以访问服务器,那么他们需要做的就是在__DIR__ . '/../db_pdo_outside_document_root.php';上使用file_get_contents -
应该考虑一下,好简单啊
-
然后我可以拒绝所有以某种方式访问该文件的推送代码。这虽然不是微不足道的,似乎有点复杂
-
也就是说,您应该设置一个不共享数据库凭据的登台服务器。然后你将负责推动一切生活。开发人员不需要在产品服务器上工作 - 随着代码库的增长,这会导致太多问题
-
+1 表示“开发人员永远不会接触生产”。开发人员喜欢在没有测试或文档的情况下说“我只是需要在 prod 中做这件事”之类的话,然后,即使它没有立即损坏,你也有这个地雷在等着你下次部署时踩到它。
标签: php security pdo web-applications