我使用 Python 和 Django 创建 Web 应用程序,我们将其存储在源代码管理中。通常设置 Django 的方式,密码在 settings.py 文件中是纯文本的。
以纯文本形式存储我的密码会给我带来许多安全问题,特别是因为这是一个开源项目,我的源代码将受到版本控制(通过 git,在 Github 上,全世界都可以看到!)
问题是,在 Django/Python 开发环境中安全地编写 settings.py 文件的最佳实践是什么?
我使用 Python 和 Django 创建 Web 应用程序,我们将其存储在源代码管理中。通常设置 Django 的方式,密码在 settings.py 文件中是纯文本的。
以纯文本形式存储我的密码会给我带来许多安全问题,特别是因为这是一个开源项目,我的源代码将受到版本控制(通过 git,在 Github 上,全世界都可以看到!)
问题是,在 Django/Python 开发环境中安全地编写 settings.py 文件的最佳实践是什么?
尽管我无法在 stackoverflow 上遇到任何特定于 Python 的内容,但我确实找到了一个很有帮助的网站,并认为我会与社区的其他人分享解决方案。
解决方案:环境变量。
注意:尽管 Linux/Unix/OS X 和 Windows 世界中的环境变量相似,但我还没有在 Windows 机器上测试过这段代码。请让我知道它是否有效。
在您的 bash/sh shell 中,键入:
export MYAPP_DB_USER='myapp'
export MYAPP_DB_PASSWORD='testing123'
在你的 Django settings.py 文件中:
DATABASE_USER = os.environ.get("MYAPP_DB_USER", '')
DATABASE_PASSWORD = os.environ.get("MYAPP_DB_PASSWORD", '')
在这种情况下,如果环境变量不存在,用户名和密码将默认为空字符串。
虽然环境变量方便了很多配置,但是把密码放在环境变量里面是不安全 的。替代方案是常规版本控制之外的配置文件,这里有一些不同的缺点:
环境变量可能会意外泄漏(通过可能通过纯文本传输到最终用户或文件系统中的意外位置(如 ~/.*sh_history)的调试通道)。
配置文件可能会意外添加到版本控制中,并最终进入没有部署权限的人可以访问的存储库中。
阅读博客文章Environment Variables Considered Harmful for Your Secrets以获得更多论据:环境可供整个进程访问,继承给子(可能还有第 3 方)进程,并且外部开发人员没有明确的假设来处理环境变量作为机密。
Python 中最简单的配置文件格式就是一个 Python 模块。
这是一个老问题,问我的人肯定已经找到了解决这个问题的方法,但我自己正在查找这个问题并认为因为这里的答案并不是我正在寻找的解决方案我可能会添加什么我为任何其他可能问同样问题的人做过。
我所做的是使用 getpass() 让设置文件在启动时要求输入密码。
from getpass import getpass
#[...]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', #or whatever DB you use
'NAME': 'mydb',
'USER': 'myuser',
'PASSWORD': getpass(),
'HOST': '',
'PORT': '',
}
}
在你的 settings.py 中有这样的东西:
db_user = 'my_db_user'
db_password = 'my_db_password'
在您的代码中硬编码有价值的信息,并且确实会带来安全风险。另一种方法是将有价值的信息(Api 密钥、数据库密码等)作为环境变量存储在本地计算机上。例如,在 linux 上,您可以添加:
export DB_USER = "my_db_user"
export DB_PASS = "my_db_password"
到您的 .bash_profile。或者,您的托管服务提供商通常可以选择设置环境变量,例如使用 AWS 弹性 beanstalk,您可以在控制台的配置下添加环境变量。
然后检索您的信息导入操作系统:
import os
db_user = os.environ.get['DB_USER']
db_password = os.environ.get['DB_PASS']