我犯了一个错误,将我的Django项目的SECRET_KEY提交到一个公共存储库中。
根据文件,这把钥匙应该是保密的。
Django项目已经上线了,并且已经有一些活跃用户运行了一段时间。如果我改变SECRET_KEY会有什么影响?将任何现有的用户、cookie、会话等。会受影响吗?显然,新的SECRET_KEY将不再存储在公共位置。
我犯了一个错误,将我的Django项目的SECRET_KEY提交到一个公共存储库中。
根据文件,这把钥匙应该是保密的。
Django项目已经上线了,并且已经有一些活跃用户运行了一段时间。如果我改变SECRET_KEY会有什么影响?将任何现有的用户、cookie、会话等。会受影响吗?显然,新的SECRET_KEY将不再存储在公共位置。
当前回答
因为提出了这个问题,Django文档已经更改为包含一个答案。
The secret key is used for: All sessions if you are using any other session backend than django.contrib.sessions.backends.cache, or are using the default get_session_auth_hash(). All messages if you are using CookieStorage or FallbackStorage. All PasswordResetView tokens. Any usage of cryptographic signing, unless a different key is provided. If you rotate your secret key, all of the above will be invalidated. Secret keys are not used for passwords of users and key rotation will not affect them.
我不清楚该如何旋转密钥。我找到了一个关于Django如何为新项目生成密钥的讨论,以及一个讨论其他选项的Gist。我最终决定让Django创建一个新项目,将新的密钥复制到我的旧项目中,然后删除新项目。
cd ~/junk # Go to some safe directory to create a new project.
django-admin startproject django_scratch
grep SECRET_KEY django_scratch/django_scratch/settings.py # copy to old project
rm -R django_scratch
更新
看起来Django在1.10版本中添加了get_random_secret_key()函数。您可以使用它来生成一个新的密钥。
$ ./manage.py shell -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
s!)5@5s79sp=92a+!f4v!1g0d0+64ln3d$xm1f_7=749ht&-zi
$ ./manage.py shell -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
_)+%kymd=f^8o_fea1*yro7atz3w+5(t2/lm2cz70*e$2mn\g3
$
其他回答
安装django extensions:
pip install django-extensions
你需要把django_extensions应用添加到你的Django项目settings.py文件的INSTALLED_APPS设置中:
INSTALLED_APPS = (
...
'django_extensions',
)
创建一个新的密钥,你可以把它放在你的settings.py模块中:
python manage.py generate_secret_key
编辑:这个答案是基于django 1.5的
SECRET_KEY被用于许多不同的地方,我将首先指出它的影响,然后尝试浏览该列表并给出影响的精确解释。
直接或间接使用SECRET_KEY的列表:
JSON object signing crypto functions for salted hmacs or seeding the random engine which impacts: password reset token comment form security to protect against forged POST requests form security protect against message tampering as the message framework may use cookies to pass messages between views. protect session data and create random session keys to avoid tampering as well. create random salt for most password hashers create random passwords if necessary create itself when using startproject create CSRF key
实际上,这里列出的很多项都通过django.utils.crypt.get_random_string()使用SECRET_KEY来为随机引擎播种。这不会受到SECRET_KEY值更改的影响。
受价值变化直接影响的用户体验包括:
sessions, the data decode will break, that is valid for any session backend (cookies, database, file based or cache). password reset token already sent won't work, users will have to ask a new one. comments form (if using django.contrib.comments) will not validate if it was requested before the value change and submitted after the value change. I think this is very minor but might be confusing for the user. messages (from django.contrib.messages) won't validate server-side in the same timing conditions as for comments form.
更新:现在在django 1.9.5上工作,快速看一下源代码给了我几乎相同的答案。之后可能会做个彻底的检查。
SECRET_KEY字符串主要用于加密和/或散列cookie数据。很多框架(包括Django)都做到了这一点,因为默认会话cookie有其自身的缺陷。
假设你在django中有一个表单,用于编辑带有隐藏字段的文章。在这个隐藏字段中存储您正在编辑的文章的ID。如果你想确保没有人可以发送任何其他文章id给你,你会添加一个额外的隐藏字段与哈希id。如果有人改变ID,你会知道,因为哈希值不一样了。
当然,这是一个简单的示例,但这是如何使用SECRET_KEY的。
Django内部使用它,例如{% csrf_token %}和其他一些东西。如果您根据您的问题和您不使用它而更改它,它真的不应该对您的应用程序产生任何影响。
唯一的问题是会话值可能会被删除。例如,用户将不得不再次登录到admin,因为django将无法用不同的密钥解码会话。
因为提出了这个问题,Django文档已经更改为包含一个答案。
The secret key is used for: All sessions if you are using any other session backend than django.contrib.sessions.backends.cache, or are using the default get_session_auth_hash(). All messages if you are using CookieStorage or FallbackStorage. All PasswordResetView tokens. Any usage of cryptographic signing, unless a different key is provided. If you rotate your secret key, all of the above will be invalidated. Secret keys are not used for passwords of users and key rotation will not affect them.
我不清楚该如何旋转密钥。我找到了一个关于Django如何为新项目生成密钥的讨论,以及一个讨论其他选项的Gist。我最终决定让Django创建一个新项目,将新的密钥复制到我的旧项目中,然后删除新项目。
cd ~/junk # Go to some safe directory to create a new project.
django-admin startproject django_scratch
grep SECRET_KEY django_scratch/django_scratch/settings.py # copy to old project
rm -R django_scratch
更新
看起来Django在1.10版本中添加了get_random_secret_key()函数。您可以使用它来生成一个新的密钥。
$ ./manage.py shell -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
s!)5@5s79sp=92a+!f4v!1g0d0+64ln3d$xm1f_7=749ht&-zi
$ ./manage.py shell -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
_)+%kymd=f^8o_fea1*yro7atz3w+5(t2/lm2cz70*e$2mn\g3
$
根据https://docs.djangoproject.com/en/dev/topics/signing/页面,SECRET_KEY主要用于临时事务——例如,通过网络发送签名数据,以便检测篡改。看起来可能会坏的东西有:
签名cookies,例如“记住我在这台计算机上的认证”类型值。在这种情况下,cookie将失效,签名将无法验证,用户将不得不重新进行身份验证。 对于任何请求密码重置或自定义文件下载链接的用户,这些链接将不再有效。用户只需重新请求这些链接。
一些比我更有Django经验的人可能会对此表示赞同,但我怀疑,除非您明确地使用签名API,否则这只会给用户带来轻微的不便。