django 中是否有生成 settings.SECRET_KEY 的函数?
Is there a function for generating settings.SECRET_KEY in django?
我写了一个 ansible-role for openwisp2 to ease its deployment, it's a series of django apps. To ease the deployment as much as possible, I wrote a simple (probably trivial) SECRET_KEY generator script ,ansible 第一次调用它来生成密钥 运行.
现在,这很好用,但我认为它破坏了 Django 在生成强密钥方面的内置安全措施,这也很难猜到。
当时我看了其他方法,但没有找到太多,现在我想知道:django中有生成settings.SECRET_KEY的函数吗?
这将避免这种自制的解决方案,即使它们有效,但在安全方面并不有效。
确实,您可以使用调用 startproject
时生成新密钥的相同函数,即 django.core.management.utils.get_random_secret_key()
。
但请注意,它与您的版本差别不大。
请注意,这在生产中使用可能不安全,正如 S Ghosh
在下面的 post 中指出的那样。但是复制并粘贴到 运行 django-admin shell
之后,例如快速获取密钥。
from django.core.management.utils import get_random_secret_key
get_random_secret_key()
运行 下面这个命令在终端上。
$ 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
我想补充一点,根据提交 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))'
S Ghosh TLDR: Generate Django Secret Key indicates that as of version 3.1.3, Django is actually using the Python secrets
module behind the scenes. Looking at this blob for get_random_secret_key
and this other blob为get_random_string
引用的post,我看是这样的:
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,最大的问题是您是否要生成依赖 Dango 的 SECRET_KEY
,或者只是 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'
我写了一个 ansible-role for openwisp2 to ease its deployment, it's a series of django apps. To ease the deployment as much as possible, I wrote a simple (probably trivial) SECRET_KEY generator script ,ansible 第一次调用它来生成密钥 运行.
现在,这很好用,但我认为它破坏了 Django 在生成强密钥方面的内置安全措施,这也很难猜到。
当时我看了其他方法,但没有找到太多,现在我想知道:django中有生成settings.SECRET_KEY的函数吗?
这将避免这种自制的解决方案,即使它们有效,但在安全方面并不有效。
确实,您可以使用调用 startproject
时生成新密钥的相同函数,即 django.core.management.utils.get_random_secret_key()
。
但请注意,它与您的版本差别不大。
请注意,这在生产中使用可能不安全,正如 S Ghosh
在下面的 post 中指出的那样。但是复制并粘贴到 运行 django-admin shell
之后,例如快速获取密钥。
from django.core.management.utils import get_random_secret_key
get_random_secret_key()
运行 下面这个命令在终端上。
$ 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
我想补充一点,根据提交 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))'
S Ghosh TLDR: Generate Django Secret Key indicates that as of version 3.1.3, Django is actually using the Python secrets
module behind the scenes. Looking at this blob for get_random_secret_key
and this other blob为get_random_string
引用的post,我看是这样的:
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,最大的问题是您是否要生成依赖 Dango 的 SECRET_KEY
,或者只是 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'