作者选择了 COVID-19 救援基金作为 Write for Donations计划的一部分接受捐款。
介绍
开发一个 Django应用程序可以是一个方便的体验,因为它是灵活和可扩展的结构。这个前提延伸到Django的安全导向设置,可以帮助你准备你的项目生产。
将设置分开,将允许您根据环境设置不同的配置。利用 `.env 来设置环境变量或隐藏机密设置,将确保您不会发布任何可能损害项目的细节。
虽然实施这些策略可能一开始看起来很耗时,但开发一个实用的工作流程将使您能够部署项目的版本,而不会损害安全性或生产力。
在本教程中,您将利用以安全为导向的工作流程为您的Django项目,通过实施和配置基于环境的设置, .env
和Django的内置安全设置。
前提条件
在您开始本指南之前,您将需要以下内容:
如果你还没有一个设置,你可以使用我们的 如何安装Django和设置开发环境设置教程。 在该教程中,你将使用这个教程的测试站
项目作为一个例子。
- 对于你的Django项目,你还需要Python 3安装。你可以使用我们的 如何在Ubuntu 20.04上安装Python 3和在Ubuntu 20.04服务器上设置编程环境教程(How To Install Python 3 and Set Up a Programming Environment)来安装它。
- 一个让我们加密证书. 如果你还没有安装一个Django项目,你可以使用我们的 How To Secure Nginx with Let's Encrypt on Ubuntu 20.04教
<$>[注] 注:如果您正在使用现有的Django项目,您可能有不同的要求.本教程建议一个特定的项目结构;然而,您也可以根据需要单独使用本教程的每个部分。
步骤 1 – 重组 Django 的设置
在进入Django项目的安全性之前,您需要进入项目目录并激活您的虚拟环境:
1cd django-apps
2. env/bin/activate
在这个第一步中,您将开始将您的settings.py
文件重组为环境特定的配置,这是当您需要在不同的环境之间移动项目时的一个很好的做法,例如,开发和生产。
在项目子目录中创建一个名为设置
的新目录:
1mkdir testsite/testsite/settings
(根据前提,本教程使用测试站点
,但您可以在这里替换您的项目名称。
此目录将取代您当前的 settings.py
配置文件;您的所有基于环境的设置都将存在于此文件夹中的单独文件中。
在新的设置
文件夹中,创建三个Python文件:
1cd testsite/testsite/settings
2touch base.py development.py production.py
development.py
文件将包含您通常在开发过程中使用的设置,而production.py
文件将包含用于生产服务器的设置,您应该将这些设置保留在单独,因为生产配置将使用在开发环境中不起作用的设置;例如,强制使用HTTPS,添加标题和使用生产数据库。
base.py
设置文件将包含由 development.py
和 production.py
继承的设置,以减少冗余,并帮助您保持代码清洁。
在您的设置
目录中,重命名settings.py
为base.py
使用以下命令:
1mv ../settings.py base.py
您刚刚完成了新的基于环境的设置目录的概述,您的项目尚未理解您的新配置,因此下一步,您将修复此问题。
步骤 2 — 使用‘django-environ’
目前,Django 不会识别你的新设置目录或其内部文件,因此,在继续使用基于环境的设置之前,你需要让Django 使用‘django-environ’。
转到项目的根目录,然后使用ls
命令列出目录的内容:
1cd ../../
2ls
您的项目根目录中的文件应该是这样的:
1[secondary_label Output]
2db.sqlite3 manage.py testsite
安裝 django-environ
:
1pip install django-environ
现在你需要配置Django以使用.env
。你将编辑两个文件来做到这一点:用于开发的manage.py
和用于生产的wsgi.py
。
首先,打开manage.py
以使用nano
或您喜爱的文本编辑器进行编辑:
1nano manage.py
添加以下突出的代码:
1[label testsite/manage.py]
2import os
3import sys
4import environ
5
6environ.Env.read_env()
7
8def main():
9 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testsite.settings')
10
11 try:
12 from django.core.management import execute_from_command_line
13 except ImportError as exc:
14 raise ImportError(
15 "Couldn't import Django. Are you sure it's installed and "
16 "available on your PYTHONPATH environment variable? Did you "
17 "forget to activate a virtual environment?"
18 ) from exc
19 execute_from_command_line(sys.argv)
20
21if __name__ == '__main__':
22 main()
保存并关闭manage.py
,按CTRL+X
,按Y
来保存,然后按ENTER
。
接下来打开wsgi.py
来编辑:
1nano testsite/wsgi.py
添加以下突出的线条:
1[label testsite/testsite/wsgi.py]
2
3import os
4import environ
5
6environ.Env.read_env()
7
8from django.core.wsgi import get_wsgi_application
9
10os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testsite.settings')
11
12application = get_wsgi_application()
保存和关闭文件,按CTRL+X
,按Y
来保存,然后按ENTER
。
您添加到这两个文件的代码可以做两件事:首先,每当 Django 运行时—‘manage.py’ 用于运行开发,‘wsgi.py’ 用于生产 — 你会告诉它寻找你的.env 文件。
最后,您将在当前目录中创建一个 .env
:
1nano .env
现在添加下列行来设置环境发展:
1[label testsite/.env]
2DJANGO_SETTINGS_MODULE="testsite.settings.development"
保存和关闭文件,按CTRL+X
,按Y
来保存,然后按ENTER
。
<$>[注]
**注:**添加 .env
到您的 .gitignore
文件,所以它永远不会包含在您的承诺中;您将使用此文件包含您不希望公开可见的密码和 API 密钥等数据。
建议在您的项目中创建一个.env.example
,这样您可以随时随地轻松创建一个新的.env
。
因此,默认情况下,Django 将使用testsite.settings.development
,但如果您将DJANGO_SETTINGS_MODULE
更改为testsite.settings.production
,它将开始使用您的生产配置。
步骤 3 – 创建开发和生产设置
接下来,您将打开您的base.py
并在单独的development.py
和production.py
文件中添加您希望对每个环境进行修改的配置。
<$>[注] 注: 根据环境,您可以根据环境来确定需要配置的设置。本教程只将涵盖生产和开发设置的一个常见例子(即安全设置和单独的数据库配置)。
在本教程中,你将使用 Django 项目从 前提教程作为示例项目. 你将设置从 base.py
移动到 development.py
. 开始打开 development.py
:
1nano testsite/settings/development.py
然后添加以下代码:
1[label testsite/testsite/settings/development.py]
2import os
3from .base import *
4
5DEBUG = True
6
7DATABASES = {
8 'default': {
9 'ENGINE': 'django.db.backends.sqlite3',
10 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
11 }
12}
保存和关闭文件,按CTRL+X
,按Y
来保存,然后按ENTER
。
首先,您将从「base.py」导入 - 此文件继承了从「base.py」的设置. 然后,您将转移您想要对开发环境进行修改的设置. 在这种情况下,开发的特定设置如下:「DEBUG」,您需要在开发中是「True」,但不是在生产中;以及「DATABASES」,本地数据库而不是生产数据库。
<$>[注]
** 注意:** 出于安全目的,Django 的 DEBUG 输出不会显示任何可能包含字符串API
,KEY
,PASS
,SECRET
,SIGNATURE
或TOKEN
的设置。
这样做是为了确保秘密不会被揭露,如果您意外地部署一个项目进入生产,但DEBUG
仍然启用。
尽管如此,永远不要在启用DEBUG
时公开部署项目,这只会危及您的项目的安全性。
接下来,你会添加到 production.py
. 用以下命令打开文件:
1nano testsite/settings/production.py
然后添加以下代码. 生产将类似于 development.py
,但具有不同的数据库配置和 DEBUG
设置为 False
:
1[label testsite/testsite/settings/production.py]
2import os
3from .base import *
4import environ
5
6env = environ.Env()
7environ.Env.read_env()
8
9DEBUG = False
10
11ALLOWED_HOSTS = []
12
13DATABASES = {
14 'default': {
15 'ENGINE': env('SQL_ENGINE', default='django.db.backends.sqlite3'),
16 'NAME': env('SQL_DATABASE', default=os.path.join(BASE_DIR, 'db.sqlite3')),
17 'USER': env('SQL_USER', default='user'),
18 'PASSWORD': env('SQL_PASSWORD', default='password'),
19 'HOST': env('SQL_HOST', default='localhost'),
20 'PORT': env('SQL_PORT', default=''),
21 }
22}
保存和关闭文件,按CTRL+X
,按Y
来保存,然后按ENTER
。
对于所提供的示例数据库配置,您可以使用 .env
来配置每个所提供的凭据,包括默认设置。
根据您所使用的示例设置,当您将项目设置为使用生产设置时,DEBUG 将变为假
,ALLOWED_HOSTS
被定义,您将开始使用您(已经)在服务器上配置的不同的数据库。
步骤 4 — 使用 Django 的安全设置
Django 包含安全设置,可供您添加到您的项目中。在此步骤中,您将为您的项目添加安全设置,这些设置被认为是任何生产项目所必需的。
在大多数情况下,这些设置将强制使用HTTPS用于各种Web功能,例如(https://en.wikipedia.org/wiki/HTTP_cookie#:~:text=A%20session%20cookie%2C%20also%20known,the%20user%20closes%20the%20browser.),CSRF Cookie,升级HTTP到HTTPS等。
首先打开production.py
:
1nano testsite/settings/production.py
在您的文件中,根据以下代码的解释,添加对您的项目工作的突出设置:
1[label testsite/testsite/settings/production.py]
2import os
3from .base import *
4import environ
5
6env = environ.Env()
7environ.Env.read_env()
8
9DEBUG = False
10
11ALLOWED_HOSTS = ['your_domain', 'www.your_domain']
12
13DATABASES = {
14 'default': {
15 'ENGINE': env('SQL_ENGINE', default='django.db.backends.sqlite3'),
16 'NAME': env('SQL_DATABASE', default=os.path.join(BASE_DIR, 'db.sqlite3')),
17 'USER': env('SQL_USER', default='user'),
18 'PASSWORD': env('SQL_PASSWORD', default='password'),
19 'HOST': env('SQL_HOST', default='localhost'),
20 'PORT': env('SQL_PORT', default=''),
21 }
22}
23
24SECURE_SSL_REDIRECT = True
25
26SESSION_COOKIE_SECURE = True
27
28CSRF_COOKIE_SECURE = True
29
30SECURE_BROWSER_XSS_FILTER = True
ALLOWED_HOSTS'是代表您项目所能服务的主机/域名的字符串列表。 这是防止攻击者给缓存和DNS下毒的安全措施. 在[Django文件](https://docs.djangoproject.com/en/4.1/ref/settings/)中查找关于
ALLOWED-HOSTS'的更多详情。 (-
) SECURE_SSL_REDIRECT' 将所有 HTTP 请求重定向到 HTTPS (除非豁免) 。 这意味着您的工程将永远尝试使用加密连接. 您需要将 SSL 配置在您的服务器上才能工作 。 请注意, 如果您已经配置了 Nginx 或 Apache 来完成此任务, 此设置将会是冗余的 。 (_) ( )* 'SESSION_COOKIE_SECURE'告诉浏览器,饼干只能通过HTTPS处理. 这意味着您为活动制作的 cookie, 如登录, 只会在加密连接上工作 。 ( _) ( )*
CSRF-COOKIE-SECURE'与SESSION-COOKIE-SECURE'相同,但适用于你的CSRF标志。 _CSRF令牌_防止[跨站请求伪造] (https://en.wikipedia.org/wiki/Cross-site_request_forgery). Django CSRF的保护通过确保向您的项目提交(登入、注册等)的任何表格都是由您的项目创建的,而不是第三方的。 (_) ( )*
SECURE_BROWSERXSS-FILTER'将`XSS-保护: 1;模式=块'标题放在所有尚未获得的回复上。 这将确保第三方不能向您的项目注入脚本 。 例如,如果用户使用公共字段在数据库中存储脚本,当该脚本被检索并显示给其他用户时,它不会运行. (
(英语)
保存和关闭文件,按CTRL+X
,按Y
来保存,然后按ENTER
。
如果您想了解更多关于 Django 中可用的不同安全设置,请参阅他们的 文档。
<$>[警告]
警告: Django 的文档指出,您不应该完全依赖 SECURE_BROWSER_XSS_FILTER
。
附加设置
以下设置支持 HTTP 严格运输安全(HSTS),这意味着您的整个网站必须随时使用 SSL。
SECURE_HSTS-SECONDS'是设定的几秒钟时间。 如果您设置这个小时( 以秒计) , 每次访问您网站上的网页, 它会告诉您的浏览器, 在接下来的一小时里, HTTPS 是您访问该网站的唯一方式 。 如果您在那个时间访问您网站的不安全部分, 浏览器会显示错误, 不安全的页面将无法访问 。 ( _) ( )*
SECURE_HSTS-PRELOAD'只有在设定SECURE_HSTS-SECONDS'的情况下才有效。 此页眉指示浏览器要 [预装] (https://hstspreload.org/] 您的网站 。 这意味着您的网站会被添加到一个硬码列表中,该列表在受欢迎的浏览器中被执行,比如Firefox和Chrome. 这需要您的网站总是加密的 。 注意这个标题很重要。 如果您在任何时间决定不为您的项目使用加密,则需要几周的时间才能从 [HSTS preload list] (https://hstspreload.org/). (_). ( )*
SECURE_HSTS_INCLUDE_SUBDOMAINS'对所有子域应用HSTS头. 启用此标题意味着您的域
和不安全的域
都需要加密, 即使不安全的域。 您的域
与 Django 项目无关 。 ( _) (英语)
<$>[警告] **警告:**错误配置这些额外设置可能会在相当长的时间内破坏您的网站。
请在实施这些设置之前阅读 Django 关于 HSTS 的文档。
需要考虑这些设置将如何与你自己的Django项目合作;总的来说,这里讨论的配置是大多数Django项目的良好基础。
步骤 5 — 使用django-environ
为秘密
本教程的最后部分将帮助您利用django-environ
。这将允许您隐藏某些信息,例如您的项目的SECRET_KEY
(https://docs.djangoproject.com/en/4.1/ref/settings/#std:setting-SECRET_KEY)或管理员的登录 URL。如果您打算在GitHub或GitLab等平台上发布代码,这是一个很好的想法,因为这些秘密不会被发布。相反,每次您在本地环境或服务器上最初设置您的项目,您可以创建一个新的.env
文件并定义这些秘密变量。
您必须隐藏您的SECRET_KEY
,以便在本节中开始工作。
在您的项目的 root 目录中打开您的 .env
文件:
1nano .env
并添加以下行,确保用自己的秘密字符串代替your_secret_key
:
1[label testsite/.env]
2DJANGO_SETTINGS_MODULE="testsite.settings.development"
3SECRET_KEY="your_secret_key"
然后通过按CTRL+X
来保存和关闭文件,按Y
来保存,然后按ENTER
。
接下来,打开base.py
:
1nano testsite/settings/base.py
更新SECRET_KEY
变量如下:
1[label testsite/testsite/settings/base.py]
2. . .
3import environ
4
5env = environ.Env()
6environ.Env.read_env()
7
8SECRET_KEY = env('SECRET_KEY')
9. . .
<$>[注]
注:SECRET_KEY
不应该被实际的秘密密密钥取代。
然后通过按CTRL+X
来保存和关闭文件,按Y
来保存,然后按ENTER
。
最后,你会通过添加一个长串随机字符来隐藏你的管理 URL,所以而不是去到your_domain/admin
,你会去到your_domain/very_secret_url/admin
。
再次打开.env
:
1nano .env
然后添加一个SECRET_ADMIN_URL
变量:
1[label testsite/.env]
2DJANGO_SETTINGS_MODULE="testsite.settings.development"
3SECRET_KEY="your_secret_key"
4SECRET_ADMIN_URL="very_secret_url"
保存和关闭文件,按CTRL+X
,按Y
来保存,然后按ENTER
。
现在你会告诉Django用SECRET_ADMIN_URL
隐藏你的管理 URL:
1nano testsite/urls.py
<$>[注]
注: 不要忘了用自己的秘密URL代替very_secret_url
。
如果你想为这个变量使用随机字符串,Python 提供了一个很棒的 secrets.py 库来生成此类字符串。
编辑 admin URL 如下:
1[label testsite/testsite/urls.py]
2from django.contrib import admin
3from django.urls import path
4import environ
5
6env = environ.Env()
7environ.Env.read_env()
8
9urlpatterns = [
10 path(env('SECRET_ADMIN_URL') + '/admin/', admin.site.urls),
11]
保存和关闭文件,按CTRL+X
,按Y
来保存,然后按ENTER
。
您现在可以找到管理员登录页面在 /very_secret_url/admin/
而不是仅仅是 /admin/
:
结论
在本教程中,您已经配置了当前的Django项目以便在不同的环境中轻松使用。您的项目现在利用django-environ
来处理秘密和设置。
如果您已按指示启用了所有推荐的安全组件和重新部署设置,则您的项目具有以下关键功能:
- SSL/HTTPS 用于所有通信(例如子域、cookie、CSRF)。
- XSS(跨网站脚本)攻击预防
- CSRF(跨网站请求伪造)攻击预防 *隐藏的项目秘密密密钥 *隐藏的管理员登录 URL,防止暴力攻击 *开发和生产的独立设置
如果您有兴趣了解更多关于Django的信息,请查看我们关于Django开发的教程系列(https://www.digitalocean.com/community/tutorial_series/django-development)。
此外,如果你还没有把你的项目投入生产,这里是关于如何在Ubuntu 20.04上设置Django使用Postgres,Nginx和Gunicorn的教程(https://andsky.com/tech/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-20-04)。
当然,请阅读 Django 的 设置文档,以获取更多信息。