使用唯一的SECRET_KEY分发Django项目

时间:2011-01-12 02:05:02

标签: django

我有一个Django项目,我想在像bitbucket或github这样的公共存储库上发布。我希望它尽可能容易安装,所以我要包括完整的项目,而不仅仅是可插拔的应用程序。这意味着还将包含settings.py文件。

如何避免每次安装settings.SECRET_KEY相同的问题?

唯一的简单解决方案是让用户手动修改settings.py吗?

我是否应该将密钥存储在默认数据库中,并且如果它不存在则settings.py初始化它?这样可以解决问题,但我想知道是否已经有一种标准的方法来做到这一点。

谢谢!

10 个答案:

答案 0 :(得分:73)

要添加Carles Barrobés所说的内容,您可以使用the method that Django uses in startproject生成新密钥:

from django.utils.crypto import get_random_string

chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
get_random_string(50, chars)

对于Django 1.10及更高版本,上面的代码片段很好地包含在一个函数中。

from django.core.management.utils import get_random_secret_key
get_random_secret_key()

Link to GitHub repo

答案 1 :(得分:39)

我会这样做:

将密钥放在单独的文件“secret_key.py”中。原始安装不存在此文件。在您的settings.py中包含以下内容:

try:
    from .secret_key import SECRET_KEY
except ImportError:
    SETTINGS_DIR = os.path.abspath(os.path.dirname(__file__))
    generate_secret_key(os.path.join(SETTINGS_DIR, 'secret_key.py'))
    from .secret_key import SECRET_KEY

您要编写的函数generate_secret_key(filename)生成一个名为filename的文件(我们称之为secret_key.py,与settings.py在同一个目录中)内容:

SECRET_KEY = '....random string....'

其中随机字符串是基于随机数生成的密钥。

对于密钥生成,您可以使用Umang的建议https://stackoverflow.com/a/16630719/166761

答案 2 :(得分:11)

使用python manage.py shell打开Django shell,然后执行以下操作在Django 2.1中创建安全的随机密钥:

>>> from django.core.management.utils import get_random_secret_key
>>> get_random_secret_key()
'[GENERATED KEY]'
>>>

注意:>>>代表shell提示符,不应键入。

答案 3 :(得分:5)

一般来说,您可以将Django配置划分为特定于应用程序的内容和特定于服务器的内容。这属于后一类。

您可以通过多种方式解决特定于服务器的配置问题,this question中对此进行了详细讨论。

对于这个特定的实例,使用我在对另一个问题的回答中概述的方法,我会在settings_local.py.sample中放置一个占位符进行分发,在安装过程中,我将其复制到{{1并编辑以适应。

答案 4 :(得分:2)

我会解决这个问题:

  • 提供虚拟密钥,例如:I_AM_A_DUMMY_KEY_CHANGE_ME
  • 创建一个管理命令以生成一个新命令:./manage.py gen_secret_key
  • 在文档中,强烈建议用户尽快运行命令

答案 5 :(得分:1)

在我的代码中,我有两个级别的设置文件,灵感来自Django的两个Scoops,所以中间的设置就像这样在基础模板中设置了BASE_PRIVATE_DIR。在我的情况下,这是来自django目录../../mysite_private,但在应用程序git下的正常文件的某处:

from .base import *

ALLOWED_HOSTS = ['staging.django.site'] 
#Allow local override which is per deployment instance.  There should probably then be
#  an instance git for version control of the production data
try:
    import sys
    private_path = BASE_PRIVATE_DIR.child('production')
    sys.path.append(private_path)
    from private_settings import *
except ImportError:
    print(" No production overide private_settings.py found.  This is probably an error  = {}".format(private_path))
    # If it doesnt' exist that is fine and just use system and environment defaults

答案 6 :(得分:1)

我在pypi.org上发现了这段代码块,几乎就像Umang的答案一样。

在您的项目目录中运行

{'slug': 'icml2015_liang_language_understanding', 'type': 'Lecture', 'obj_id': 23694, 'video': 1, 'video_id': 23648, 'videos': [1, 2], 'chrome_colors': ['FFFFFF', 'F21F1F'], 'livepipe': '//videolectures.net', 'site_slug': 'vln', 'media_url': 'https://static.videolectures.net/r.1483388978/', 'sentry': '//161ef9a5c3a14af1848399909b890522@sentry.viidea.com/6'}
[('rtmp', 'mp4:v012/01/ae6se7y42if65i27glt3yfanffv5rvtk.mp4'), ('m3u8', 'http://hydro2.videolectures.net/vod/_definst_/mp4:v012/01/ae6se7y42if65i27glt3yfanffv5rvtk.mp4/playlist.m3u8'), ('secure_download', 'http://videolectures.net/site/secure_dl/14f30db64e8184a24b2bb4414dcfdc5d/5f8127f8/ae6se7y42if65i27glt3yfanffv5rvtk/tag=1001866/icml2015_liang_language_understanding_01_400x300_h264.mp4'), ('http', 'http://hydro.ijs.si/v012/01/ae6se7y42if65i27glt3yfanffv5rvtk.mp4')]
('http', 'http://hydro.ijs.si/v012/01/ae6se7y42if65i27glt3yfanffv5rvtk.mp4')

这将生成一个包含随机Django秘密密钥的新文件python manage.py generate_secret_key [--replace] [secretkey.txt] 。在生产设置文件中,将密钥替换为生成的密钥。

或者为了避免对密钥进行硬编码。添加以下代码段,以便当您始终运行该程序时,新的秘密密钥将为您生成一个更新的密钥。

secretkey.txt

OR

import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))

# Use a separate file for the secret key
with open(os.path.join(BASE_DIR, 'secretkey.txt')) as f:
    SECRET_KEY = f.read().strip()

答案 7 :(得分:0)

如果您使用模板创建新项目,例如django-admin.py startproject --template=path_to_template project_name只需将{{ secret_key }}放入项目模板设置文件(例如settings.py),例如SECRET_KEY = '{{ secret_key }}',Django就会为您生成

答案 8 :(得分:0)

在此解决方案中,我使用django-dotenv,这是我的项目的依赖项之一,如requirements.txt中列出的django-dotenv==1.4.1。这种方法的优点是,对于安装应用程序的每个环境,您都有一个不同的.env文件。

使用以下内容在utils.py的同一目录中创建文件settings.py

from django.utils.crypto import get_random_string

def generate_secret_key(env_file_name):
    env_file = open(env_file_name, "w+")
    chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
    generated_secret_key = get_random_string(50, chars)
    env_file.write("SECRET_KEY = '{}'\n".format(generated_secret_key))
    env_file.close()

然后按如下方式修改settings.py文件:

import dotenv
from [project-folder-name] import utils
...
try:
    SECRET_KEY = os.environ['SECRET_KEY']
except KeyError:
    path_env = os.path.join(BASE_DIR, '.env')
    utils.generate_secret_key(path_env)
    dotenv.read_dotenv(path_env)
    SECRET_KEY = os.environ['SECRET_KEY']

对于那些不使用django-dotenv的人,您只需将其添加为依赖项并更改manage.py以在启动时加载它:

import dotenv

if __name__ == "__main__":
    dotenv.read_dotenv()

答案 9 :(得分:0)

Carles Barrobés给出了一个很好的答案,但是它不完整,这是我的python 3版本,缺少功能。

from django.core.management.utils import get_random_secret_key

def generate_secret_key (filepath):
    secret_file = open(filepath, "w")
    secret = "SECRET_KEY= " + "\""+ get_random_secret_key() + "\"" + "\n"
    secret_file.write(secret)
    secret_file.close()

try:
    from .secret_key import SECRET_KEY
except ModuleNotFoundError:

    SETTINGS_DIR = os.path.abspath(os.path.dirname(__file__))
    generate_secret_key(os.path.join(SETTINGS_DIR, 'secret_key.py'))
    from .secret_key import SECRET_KEY

请注意,我将ImportError更改为ModuleNotFoundError,并创建了python文件secret_key.py来像收集变量一样收集SECRET_KEY而不是解析txt文件。