在我正在编写的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对象,而不是在文件中定义常量,而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所指出的那样,应用程序的代码当然仍然可以获取文件的内容并因此可以访问凭据,因此我的整体推理是不正确的,因为它没有考虑这种非常简单的情况。 猜猜我必须找到另一种策略,如果有的话...
答案 0 :(得分:1)
您可以结合两种策略:
1。将开发环境和生产环境分开
最简单的方法是使它们“包含”数据库的位置,使用的帐户以及配置文件的密码,这些配置文件在产品的生产和开发方面是不同的。
->这样,开发人员根本不会了解产品生产方面的敏感部分。
2。为用户提供个人帐户
将您的开发人员个人帐户提供给您的开发数据库服务器,以便他们获得(个人)数据库,他们可以执行所有操作,而您仍然可以拥有测试环境,可以使用更像生产数据库的数据库(和因此可以更好地控制他们可能发生的事情
这需要对每个新招聘的开发人员进行一点用户管理,并在他们离开时采取一些措施,但是让您的内部IT支持人员在清单上再添加一个项目以及创建/删除电子邮件并没有那么困难地址等。
如果在开发方面,您给它们提供了单独的配置文件,并且最终准备好投入生产,则效果最好。
->这为开发人员提供了一个区域,他们可以在不影响彼此的情况下做任何喜欢的事,一旦他们离开,就可以将其全部存档并脱机。
答案 1 :(得分:0)
如果您有开发服务器和生产服务器,则开发人员无需知道生产数据库的密码。如果您的开发人员直接在生产服务器上工作,那么实际上是无法避免问题的。通常,只有sysadmin / devops知道数据库密码,然后在生产服务器中进行设置。您的开发人员应该对此具有0访问权限。
答案 2 :(得分:0)
最常见的解决方案是使用.env
文件存储代码库所需的凭据。
开发人员使用开发凭据获取(/制作/自定义).env
文件,生产凭据仅在生产环境中可用。
此.env
文件保留在文档根目录中,但未随代码一起分发:它未添加到存储库(git / svn)
通常,基本开发变量中包含一个.env.example
文件,例如用于外部API的测试环境的路径以及用于其本地数据库的示例数据库凭据的路径。与.env
相比,.env.example
被添加到源控制库中。
就代码而言,您可以使用dotenv之类的库来读取.env
文件的值。
假设您想保护自己免受恶意开发人员的后门攻击,则可以使用代码审查来防止此类尝试。在现代软件生产公司以及开源项目中,标准做法是只允许将经过审查的代码合并到master分支中。
代码审查还具有许多其他好处:对代码的每个部分都多加关注可以防止错误并鼓励开发人员互相学习。
遵循这样的协议时,单个开发人员几乎不可能访问生产凭证。