在 django 中是不是有生成 settings.SECRET_KEY 的功能?
Posted
技术标签:
【中文标题】在 django 中是不是有生成 settings.SECRET_KEY 的功能?【英文标题】:Is there a function for generating settings.SECRET_KEY in django?在 django 中是否有生成 settings.SECRET_KEY 的功能? 【发布时间】:2017-05-09 00:18:39 【问题描述】:我写了一个ansible-role for openwisp2 来简化它的部署,它是一系列django 应用程序。为了尽可能简化部署,我编写了一个简单的(可能是微不足道的)SECRET_KEY generator script,在 ansible playbook 第一次运行时,ansible 会调用它来生成密钥。
现在,这很好用,但我认为它破坏了 Django 在生成强密钥方面的内置安全措施,这也很难猜到。
当时看了其他的方法但是没找到太多,现在想知道:django有生成settings.SECRET_KEY的函数吗?
这样就可以避免这种自制的解决方案,即使它们有效,但在安全性方面却无效。
【问题讨论】:
【参考方案1】:S Ghosh TLDR: Generate Django Secret Key 引用的帖子表明,截至 3.1.3 版本,Django 实际上在后台使用 Python secrets
模块。查看this blob 对应get_random_secret_key
和this other blob 对应get_random_string
,我可以看到是这样的:
def get_random_secret_key():
"""
Return a 50 character random string usable as a SECRET_KEY setting value.
"""
chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
return get_random_string(50, chars)
def get_random_string(length, allowed_chars=RANDOM_STRING_CHARS):
"""
Return a securely generated random string.
The bit length of the returned value can be calculated with the formula:
log_2(len(allowed_chars)^length)
For example, with default `allowed_chars` (26+26+10), this gives:
* length: 12, bit length =~ 71 bits
* length: 22, bit length =~ 131 bits
"""
return ''.join(secrets.choice(allowed_chars) for i in range(length))
我在代码中看到的get_random_secret_key
函数的唯一问题是允许的字符不包括大写字母,因此相同大小密钥的可能位数小于大写字母时的位数包括,但不多:
from math import log2
lower_plus_numbers = (list(chr(o) for o in range(0x61, 0x7B))
+ list(chr(o) for o in range(0x30, 0x3A)))
punctuation = list('!@#$%^&*(-_=+)')
upper_alpha = list(chr(o) for o in range(0x41, 0x5B))
shorter = log2((len(lower_plus_numbers) + len(punctuation)) ** 50)
longer = log2((len(lower_plus_numbers) + len(punctuation) + len(upper_alpha)) ** 50)
print(f'longer: int(longer + 0.5); shorter: int(shorter + 0.5) '
f'difference: int(longer - shorter + 0.5); ratio: longer/shorter')
以上代码的输出:
longer: 312; shorter: 282; difference: 30; ratio: 1.1070316647619918
所以,如果你有足够新的 Django 和 Python,最大的问题是你是想生成你的 SECRET_KEY
依赖于 Dango,还是只生成 Python。如果您不介意 Django 依赖,但想要包含大写字母,或者想要更长的键,您可以轻松地执行以下操作:
from django.utils.crypto import get_random_string
key_length = 60
get_random_string(
key_length,
allowed_chars=lower_plus_numbers + punctuation + upper_alpha,
)
样本输出:
'gW(VDtylhoAuZNcLbIC=ai5=2*tPZ=Gmf4D1^4T!NxX3tB0%_w7pYY2+FgDx'
如果您不想要 Django 依赖项,您可以使用 S Ghosh 的答案。或者,如果您想要的不仅仅是十六进制字符,您可以执行以下操作:
allowed_chars = [chr(i) for i in range(0x21, 0x7F)]
key_length = 60
key = ''.join(secrets.choice(allowed_chars) for i in range(key_length))
key
的值(作为 python 字符串):
'DN7tbWid#q6R^=%i"[1AA>$@AZg=XD+p|[aB?:#V`:kKWL77P6dC,~(\\9O\'j'
【讨论】:
【参考方案2】:我想补充一点,根据提交Fixed #31757 -- Adjusted system check for SECRET_KEY to warn about autogenerated default keys,方法get_random_secret_key()
被认为是不安全的。
如果您使用的是 python 3.6+,那么您可以使用 secrets.token_hex([nbytes=None])
函数
python3 -c 'import secrets; print(secrets.token_hex(100))'
信用TLDR: Generate Django Secret Key
【讨论】:
【参考方案3】:在终端上运行以下命令。
$ python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'
输出:
2x$e%!k_u_0*gq0s4!_u(2(^lpy&gir0hg)q&5nurj0-sseuav
【讨论】:
【参考方案4】:对于像我这样的懒人:
from django.core.management.utils import get_random_secret_key
get_random_secret_key()
【讨论】:
不懒惰。实用;)【参考方案5】:确实,您可以使用与调用startproject
时生成新密钥相同的函数,即django.core.management.utils.get_random_secret_key()
。
请注意,它与您的版本并没有太大区别。
【讨论】:
我认为它内置了更多安全性,但我错了。无论如何,使用该功能可能会更好,因为将来可能会对其进行改进。 其实get_random_string
比我的版本好一点:github.com/django/django/blob/master/django/utils/…
在settings.py中写可以吗? SECRET_KEY=django.core.management.utils.get_random_secret_key()
@Psddp 你可以这样做,但这意味着每次你的应用程序启动/重新启动时,你都会获得一个新的密钥,这意味着所有现有的会话、cookie 等都将失效.如果这不是您使用或关心的东西,那么它可能会起作用,但仍然感觉不应该这样做。以上是关于在 django 中是不是有生成 settings.SECRET_KEY 的功能?的主要内容,如果未能解决你的问题,请参考以下文章
eclipse中是不是有生成资源的快捷方式(构造函数,get/set .....)
Django ManyToMany 字段的 set() 操作是不是清除现有关系?
django 有model生成SQL以及现有反向表生成model