EXCEL中一个简单又不简单的单元格有哪些秘密(excel一个单元格内容)
1096
2022-05-30
目录
从 Django 和 WSGIServer 开始
设置云虚拟机 (VM)
创建一个 Cookie-Cutter Django 应用程序
在开发中使用 Django 的 WSGIServer
使用 Django、Gunicorn 和 Nginx 将您的网站放到网上
设置静态公共 IP 地址
链接到域
用 Gunicorn 替换 WSGIServer
合并 Nginx
直接使用 Nginx 提供静态文件
使用 HTTPS 使您的网站做好生产准备
开启 HTTPS
将 HTTP 重定向到 HTTPS
使用 HSTS 更进一步
设置 Referrer-Policy 标头
添加内容安全策略 (CSP) 标头
生产部署的最后步骤
测试您网站的 HTTPS 安全性
结论
进一步阅读
将Django应用程序从开发到生产是一个艰巨但有益的过程。本教程将带您逐步完成该过程,提供深入的指南,从简单的 Django 应用程序开始,并添加Gunicorn、Nginx、域注册和以安全为中心的HTTP 标头。阅读本教程后,您将能够更好地将 Django 应用程序投入生产并向全世界提供。
在本教程中,您将学习:
如何将 Django 应用程序从开发带到生产
如何在现实世界的公共领域托管您的应用程序
如何将Gunicorn和Nginx引入请求和响应链
HTTP 标头如何加强您网站的 HTTPS 安全性
为了充分利用本教程,您应该对 Python、Django和 HTTP 请求的高级机制有一个入门级的理解。
您可以通过以下链接下载本教程中使用的 Django 项目:
从 Django 和 WSGIServer 开始
您将使用Django作为 Web 应用程序核心的框架,将其用于 URL 路由、HTML 呈现、身份验证、管理和后端逻辑。在本教程中,您将用另外两个层Gunicorn和Nginx补充 Django 组件,以便可扩展地为应用程序提供服务。但在此之前,您需要设置环境并使 Django 应用程序本身启动并运行。
设置云虚拟机 (VM)
首先,您需要启动并设置一个虚拟机 (VM),Web 应用程序将在该虚拟机 (VM)上运行。您应该至少熟悉一个基础架构即服务 (IaaS)云服务提供商来配置 VM。本节将引导您完成整个过程,但不会详细介绍每个步骤。
使用 VM 为 Web 应用程序提供服务是 IaaS 的一个示例,您可以在其中完全控制服务器软件。除了 IaaS 之外,其他选项确实存在:
一个无服务器架构允许您只组成Django应用程序,让一个单独的框架或云提供商处理基础设施方面。
一个集装箱方法允许多个应用程序在同一主机操作系统上独立运行。
但是,在本教程中,您将使用直接在 IaaS 上为 Nginx 和 Django 提供服务的行之有效的途径。
两个流行的虚拟机选项是腾讯 VM和阿里 EC2。要获得有关启动实例的更多帮助,您应该参考云提供商的文档:
对于 腾讯 VM,请按照他们的快速入门指南在 腾讯 门户中创建 Linux 虚拟机。
对于 阿里 EC2,了解如何进行设置。
Django 项目和本教程中涉及的所有其他内容都位于运行 Ubuntu Server 20.04的t2.micro 阿里 EC2 实例上。
VM 设置的一个重要组成部分是入站安全规则。这些是控制到您的实例的入站流量的细粒度规则。为初始开发创建以下入站安全规则,您将在生产中修改这些规则:
现在,您将一次浏览这些内容:
规则 1允许 TCP 通过端口 8000 来自您个人计算机的 IPv4 地址,允许您在开发过程中通过端口 8000 向 Django 应用程序发送请求。
规则 2允许来自分配给同一安全组的网络接口和实例的入站流量,使用安全组 ID 作为源。这是您应该绑定到您的实例的默认 AWS 安全组中包含的规则。
规则 3允许您从您的个人计算机通过 SSH 访问您的 VM。
您还需要添加出站规则以允许出站流量执行诸如安装包之类的操作:
综合起来,您的初始 AWS 安全规则集可以包含三个入站规则和一个出站规则。这些又来自三个独立的安全组——默认组、一个用于 HTTP 访问的组和一个用于 SSH 访问的组:
然后,您可以从本地计算机通过SSH 连接到实例:
$ ssh -i ~/.ssh/
此命令将您以用户身份登录到您的 VM ubuntu。这里~/.ssh/
有了这个,您应该已经准备好继续构建您的应用程序了。
创建一个 Cookie-Cutter Django 应用程序
在本教程中,您不关心使用复杂的 URL 路由或高级数据库功能制作一个花哨的 Django 项目。相反,您需要简单、小巧且易于理解的东西,让您可以快速测试您的基础架构是否正常工作。
为此,您可以执行以下步骤来设置您的应用程序。
首先,通过 SSH 连接到您的 VM 并确保您安装了 Python 3.8 和 SQLite3 的最新补丁版本:
$ sudo apt-get update -y $ sudo apt-get install -y python3.8 python3.8-venv sqlite3 $ python3 -V Python 3.8.10
这里,Python 3.8 是系统 Python,或者是python3Ubuntu 20.04 (Focal) 附带的版本。升级发行版可确保您收到来自最新 Python 3.8.x 版本的错误和安全修复。或者,您可以完全安装另一个 Python 版本 - 例如python3.9- 与系统范围的解释器一起安装,您需要将其显式调用为python3.9.
接下来,创建并激活一个虚拟环境:
$ cd # Change directory to home directory $ python3 -m venv env $ source env/bin/activate
现在,安装 Django 3.2:
$ python -m pip install -U pip 'django==3.2.*'
您现在可以使用 Django 的管理命令引导 Django 项目和应用程序:
$ mkdir django-gunicorn-nginx/ $ django-admin startproject project django-gunicorn-nginx/ $ cd django-gunicorn-nginx/ $ django-admin startapp myapp $ python manage.py migrate $ mkdir -pv myapp/templates/myapp/
这会在myapp名为 的项目旁边创建 Django 应用程序project:
/home/ubuntu/ │ ├── django-gunicorn-nginx/ │ │ │ ├── myapp/ │ │ ├── admin.py │ │ ├── apps.py │ │ ├── __init__.py │ │ ├── migrations/ │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── templates/ │ │ │ └── myapp/ │ │ ├── tests.py │ │ └── views.py │ │ │ ├── project/ │ │ ├── asgi.py │ │ ├── __init__.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py | | │ ├── db.sqlite3 │ └── manage.py │ └── env/ ← Virtual environment
使用诸如Vim或GNU nano 之类的终端编辑器,打开project/settings.py您的应用程序并将其附加到INSTALLED_APPS:
# project/settings.py INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "myapp", ]
接下来,打开myapp/templates/myapp/home.html并创建一个简短的 HTML 页面:
Now this is some sweet HTML!
之后,编辑myapp/views.py以呈现该 HTML 页面:
from django.shortcuts import render def index(request): return render(request, "myapp/home.html")
现在创建并打开myapp/urls.py以将您的视图与 URL 模式相关联:
from django.urls import path from . import views urlpatterns = [ path("", views.index, name="index"), ]
之后,相应地编辑project/urls.py:
from django.urls import include, path urlpatterns = [ path("myapp/", include("myapp.urls")), path("", include("myapp.urls")), ]
在此期间,您还可以做一件事,即确保用于加密签名的 Django密钥不是硬编码的settings.py,Git 可能会跟踪它。从 中删除以下行project/settings.py:
SECRET_KEY = "django-insecure-o6w@a46mx..." # Remove this line
将其替换为以下内容:
import os # ... try: SECRET_KEY = os.environ["SECRET_KEY"] except KeyError as e: raise RuntimeError("Could not find a SECRET_KEY in environment") from e
这告诉 Django 在您的环境中查找SECRET_KEY而不是将其包含在您的应用程序源代码中。
注意:对于较大的项目,请查看django-environ使用环境变量配置 Django 应用程序。
最后,在您的环境中设置密钥。以下是在 Ubuntu Linux 上使用OpenSSL将密钥设置为八十个字符的字符串的方法:
$ echo "export SECRET_KEY='$(openssl rand -hex 40)'" > .DJANGO_SECRET_KEY $ source .DJANGO_SECRET_KEY
您可以cat的内容.DJANGO_SECRET_KEY看到,openssl已经产生了一个加密的安全十六进制字符串键值:
$ cat .DJANGO_SECRET_KEY export SECRET_KEY='26a2d2ccaf9ef850...'
好了,你已经准备好了。这就是拥有最低限度功能的 Django 应用程序所需的全部内容。
在开发中使用 Django 的 WSGIServer
在本节中,您将使用 来测试 Django 的开发 Web 服务器httpie,这是一个很棒的命令行 HTTP 客户端,用于测试从控制台发送到您的 Web 应用程序的请求:
$ pwd /home/ubuntu $ source env/bin/activate $ python -m pip install httpie
您可以创建一个别名,让您向应用程序发送GET请求httpie:
$ # Send GET request and follow 30x Location redirects $ alias GET='http --follow --timeout 6'
这别名GET为http具有一些默认标志的调用。您现在可以使用GET docs.python.org从 Python 文档的主页查看响应标头和正文。
在启动 Django 开发服务器之前,您可以检查您的 Django 项目是否存在潜在问题:
$ cd django-gunicorn-nginx/ $ python manage.py check System check identified no issues (0 silenced).
如果您的检查没有发现任何问题,那么告诉 Django 的内置应用程序服务器开始侦听本地主机,使用默认端口 8000:
$ # Listen on 127.0.0.1:8000 in the background $ nohup python manage.py runserver & $ jobs -l [1]+ 43689 Running nohup python manage.py runserver &
使用在后台nohup
注意:如果它出现nohup挂起并让您没有光标,请按Enter以恢复终端光标和 shell 提示。
runserver反过来,Django 的命令使用以下语法:
$ python manage.py runserver [address:port]
如果address:port如上所述未指定参数,Django 将默认监听localhost:8000. 您还可以使用该lsof命令更直接地验证是否python调用了某个命令来侦听端口 8000:
$ sudo lsof -n -P -i TCP:8000 -s TCP:LISTEN COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME python 43689 ubuntu 4u IPv4 45944 0t0 TCP 127.0.0.1:8000 (LISTEN)
在本教程的这一点上,您的应用程序仅侦听localhost,即地址127.0.0.1。它尚不能从浏览器访问,但您仍然可以通过GET从 VM 本身的命令行向它发送请求来为其提供第一个访问者:
$ GET :8000/myapp/ HTTP/1.1 200 OK Content-Length: 182 Content-Type: text/html; charset=utf-8 Date: Sat, 25 Sep 2021 00:11:38 GMT Referrer-Policy: same-origin Server: WSGIServer/0.2 CPython/3.8.10 X-Content-Type-Options: nosniff X-Frame-Options: DENY
Now this is some sweet HTML!
标头Server: WSGIServer/0.2 CPython/3.8.10描述了生成响应的软件。在这种情况下,它的0.2版本WSGIServer一起CPython的3.8.10。
WSGIServer无非是 Django 定义的一个 Python 类,它实现了 Python WSGI 协议。这意味着它遵循Web 服务器网关接口 (WSGI),该标准定义了Web 服务器软件和Web 应用程序交互的方式。
到目前为止,在我们的示例中,django-gunicorn-nginx/项目是 Web 应用程序。由于您正在为开发中的应用程序提供服务,因此实际上没有单独的 Web 服务器。Django 使用simple_server实现轻量级 HTTP 服务器的模块,并将 Web 服务器与应用服务器的概念融合到一个命令中,runserver.
接下来,您将了解如何通过将您的应用与现实世界的域相关联来开始向其介绍您的应用。
使用 Django、Gunicorn 和 Nginx 将您的网站放到网上
此时,您的站点可以在您的 VM 上本地访问。如果您希望通过真实的 URL 访问您的站点,则需要声明一个域名并将其绑定到 Web 服务器。这对于启用 HTTPS 也是必要的,因为某些证书颁发机构不会为您不拥有的裸 IP 地址或子域颁发证书。在本节中,您将看到如何注册和配置域。
设置静态公共 IP 地址
如果您可以将域的配置指向一个保证不会更改的公共 IP 地址,那就再理想不过了。云虚拟机的一个次优属性是,如果实例处于停止状态,它们的公共 IP 地址可能会更改。或者,如果您出于某种原因需要用新实例替换现有 VM,则由此产生的 IP 地址更改将是有问题的。
这种困境的解决方案是将静态 IP 地址绑定到实例:
腾讯将其称为弹性 IP 地址。
按照您的云提供商的文档将静态 IP 地址与您的云 VM 相关联。在用于本教程示例的 AWS 环境中,弹性 IP 地址50.19.125.152与 EC2 实例相关联。
注意:请记住,这意味着您需要更改目标 IPssh才能通过 SSH 连接到您的 VM:
$ ssh [args] my-new-static-public-ip
更新目标 IP 后,您将能够连接到云 VM。
在您的 VM 前使用更稳定的公共 IP,您就可以链接到域了。
链接到域
在本节中,您将逐步了解如何购买、设置域名并将其链接到现有应用程序。
这些示例使用Namecheap,但请不要将其视为明确的认可。还有很多其他选项,例如domain.com、GoDaddy和Google Domains。就偏向性而言,Namecheap 为成为本教程中的首选域注册商而支付了 0 美元。
警告:如果您想在公共域上为您的站点提供服务并DEBUG设置为True,您需要创建自定义入站安全规则以仅允许您的个人计算机和 VM 的 IP 地址。你应该不打开任何HTTP或HTTPS入站规则,0.0.0.0直到你关闭DEBUG至少是。
您可以通过以下方式开始:
在Namecheap上创建一个帐户,确保设置双因素身份验证 (2FA)。
从主页开始搜索适合您预算的域名。您会发现价格可能因顶级域 (TLD) 和主机名而异。
当您对选择感到满意时购买域。
本教程使用域supersecure.codes,但您将拥有自己的域。
注意:在您阅读本教程时,请记住这supersecure.codes只是一个示例域,并没有得到积极维护。
在选择您自己的域时,请记住,选择更深奥的站点名称和顶级域 (TLD) 通常会导致购买该域的标价更便宜。这对于测试目的尤其有用。
一旦你有你的域名,你要打开WithheldForPrivacy保护,正式称为WhoisGuard。当有人whois在您的域上进行搜索时,这将掩盖您的个人信息。以下是如何执行此操作:
选择帐户 → 域列表。
选择您的域旁边的管理。
启用WithheldForPrivacy保护。
接下来,是时候为您的站点设置 DNS 记录表了。每个 DNS 记录将成为数据库中的一行,告诉浏览器完全限定域名 (FQDN)指向的底层 IP 地址。在这种情况下,我们想要supersecure.codes路由到 50.19.125.152,VM 可以到达的公共 IPv4 地址:
选择帐户 → 域列表。
选择您的域旁边的管理。
选择高级 DNS。
在Host Records 下,为您的域添加两个A 记录。
如下添加 A 记录,替换50.19.125.152为您实例的公有 IPv4 地址:
一个A记录可以让你一个域名或子站点,你为你的应用程序的Web服务器的IPv4地址相关联。在上面,值字段应使用您的 VM 实例的公共 IPv4 地址。
您可以看到Host字段有两种变体:
在这种情况下,使用@指向根域supersecure.codes。
Usingwww意味着www.supersecure.codes将指向与 just 相同的位置supersecure.codes。从技术上讲,这www是一个子域,可以将用户发送到与较短的supersecure.codes.
设置 DNS 主机记录表后,您最多需要等待 30 分钟,路由才会生效。您现在可以终止现有runserver进程:
$ jobs -l [1]+ 43689 Running nohup python manage.py runserver & $ kill 43689 [1]+ Done nohup python manage.py runserver
您可以pgrep通过再次检查活动作业来确认该过程已经结束:
$ pgrep runserver # Empty $ jobs -l # Empty or 'Done' $ sudo lsof -n -P -i TCP:8000 -s TCP:LISTEN # Empty $ rm nohup.out
有了这些东西,您还需要调整 Django 设置ALLOWED_HOSTS,它是您让 Django 应用程序提供服务的域名集:
# project/settings.py # Replace 'supersecure.codes' with your domain ALLOWED_HOSTS = [".supersecure.codes"]
前导点 ( .) 是子域通配符,允许www.supersecure.codes和supersecure.codes。保持此列表紧密以防止 HTTP主机标头攻击。
现在你可以通过一个轻微的改变来重新启动 WSGIServer:
$ nohup python manage.py runserver '0.0.0.0:8000' &
注意address:port参数 now 0.0.0.0:8000,而之前没有指定:
指定 noaddress:port意味着在 上提供应用程序localhost:8000。这意味着只能从 VM 内部访问该应用程序。您可以通过httpie从相同的 IP 地址调用来与它通话,但是您无法从外部世界访问您的应用程序。
指定一个address:portof'0.0.0.0:8000'使您的服务器对外界可见,但默认情况下仍然在端口 8000 上。该0.0.0.0简写为“绑定到所有IP地址,此计算机支持。” 对于带有一个名为 的网络接口控制器 (NIC)的开箱即用云 VM eth0, using0.0.0.0充当机器的公共 IPv4 地址的替代品。
接下来,打开输出nohup.out以查看来自 Django 的 WSGIServer 的任何传入日志:
$ tail -f nohup.out
现在是真相的时刻。是时候让您的网站成为第一位访问者了。在您的个人计算机上,在 Web 浏览器中输入以下 URL:
http://www.supersecure.codes:8000/myapp/
将上面的域名替换为您自己的域名。您应该会看到页面快速响应:
由于您之前创建的入站安全规则,您可以访问此 URL,但其他人无法访问。
故障连接故障排除显示隐藏
现在返回到您的 VM 的外壳。在 的连续输出中tail -f nohup.out,您应该看到如下所示的内容:
[
恭喜,您刚刚迈出了创建自己网站的里程碑式的第一步!但是,在这里暂停并注意 URL 中嵌入的几个大问题http://www.supersecure.codes:8000/myapp/:
该站点仅通过 HTTP 提供服务。如果不启用 HTTPS,如果您想将任何敏感数据从客户端传输到服务器,反之亦然,则您的站点从根本上是不安全的。使用 HTTP 意味着请求和响应以纯文本形式发送。你很快就会解决这个问题。
URL 使用非标准端口 8000与标准默认 HTTP 端口号 80。它非常规且有点碍眼,但您还不能使用 80。那是因为端口 80 是特权端口,非 root 用户不能——也不应该——绑定到它。稍后,您将在组合中引入一个工具,允许您的应用程序在端口 80 上可用。
如果您检查您的浏览器,您将看到您的浏览器 URL 栏提示这一点。如果您使用的是 Firefox,则会出现一个红色锁形图标,表示连接是通过 HTTP 而不是 HTTPS:
展望未来,您希望使操作合法化。您可以开始通过标准端口 80 为 HTTP 提供服务。更好的是,开始提供 HTTPS (443) 服务并将 HTTP 请求重定向到那里。您很快就会看到如何逐步完成这些步骤。
用 Gunicorn 替换 WSGIServer
您想开始将您的应用程序推向为外部世界做好准备的状态吗?如果是这样,那么您应该用manage.py runserver单独的专用应用程序服务器替换 Django 的内置 WSGIServer,它是 使用的应用程序服务器。但是等一下:WSGIServer 似乎工作得很好。为什么要更换?
要回答这个问题,您可以阅读 Django 文档的内容:
请勿在生产环境中使用此服务器。它没有经过安全审计或性能测试。(这就是它的保留方式。我们的工作是制作 Web 框架,而不是 Web 服务器,因此改进此服务器以使其能够处理生产环境超出了 Django 的范围。)(来源)
Django 是一个Web 框架,而不是一个 Web 服务器,它的维护者希望明确区分。在本节中,您将runserver用Gunicorn替换 Django 的命令。Gunicorn 首先是一个 Python WSGI 应用程序服务器,并且是经过实战考验的服务器:
它快速、优化且专为生产而设计。
它使您可以更精细地控制应用程序服务器本身。
它有更完整和可配置的日志记录。
它已经过充分测试,特别是它作为应用程序服务器的功能。
您可以将 Gunicorn 安装pip到您的虚拟环境中:
$ pwd /home/ubuntu $ source env/bin/activate $ python -m pip install 'gunicorn==20.1.*'
接下来,您需要进行一些级别的配置。Gunicorn 配置文件很酷的一点是,它只需要是有效的 Python 代码,变量名与参数相对应。您可以在一个项目子目录中存储多个 Gunicorn 配置文件:
$ cd ~/django-gunicorn-nginx $ mkdir -pv config/gunicorn/ mkdir: created directory 'config' mkdir: created directory 'config/gunicorn/'
接下来,打开一个开发配置文件config/gunicorn/dev.py,并添加以下内容:
"""Gunicorn *development* config file""" # Django WSGI application path in pattern MODULE_NAME:VARIABLE_NAME wsgi_app = "project.wsgi:application" # The granularity of Error log outputs loglevel = "debug" # The number of worker processes for handling requests workers = 2 # The socket to bind bind = "0.0.0.0:8000" # Restart workers when code changes (development only!) reload = True # Write access and error info to /var/log accesslog = errorlog = "/var/log/gunicorn/dev.log" # Redirect stdout/stderr to log file capture_output = True # PID file so you can easily fetch process ID pidfile = "/var/run/gunicorn/dev.pid" # Daemonize the Gunicorn process (detach & enter background) daemon = True
在启动 Gunicorn 之前,您应该停止该runserver过程。使用jobs找到它,并kill阻止它:
$ jobs -l [1]+ 26374 Running nohup python manage.py runserver & $ kill 26374 [1]+ Done nohup python manage.py runserver
接下来,确保上面 Gunicorn 配置文件中设置的值的日志和 PID 目录存在:
$ sudo mkdir -pv /var/{log,run}/gunicorn/ mkdir: created directory '/var/log/gunicorn/' mkdir: created directory '/var/run/gunicorn/' $ sudo chown -cR ubuntu:ubuntu /var/{log,run}/gunicorn/ changed ownership of '/var/log/gunicorn/' from root:root to ubuntu:ubuntu changed ownership of '/var/run/gunicorn/' from root:root to ubuntu:ubuntu
使用这些命令,您已确保 Gunicorn 存在必要的 PID 和日志目录,并且它们可由ubuntu用户写入。
有了这个,您可以使用-c标志启动 Gunicorn以指向项目根目录中的配置文件:
$ pwd /home/ubuntu/django-gunicorn-nginx $ source .DJANGO_SECRET_KEY $ gunicorn -c config/gunicorn/dev.py
这gunicorn使用dev.py您在上面指定的开发配置文件在后台运行。和以前一样,您现在可以监视输出文件以查看 Gunicorn 记录的输出:
$ tail -f /var/log/gunicorn/dev.log [2021-09-27 01:29:50 +0000] [49457] [INFO] Starting gunicorn 20.1.0 [2021-09-27 01:29:50 +0000] [49457] [DEBUG] Arbiter booted [2021-09-27 01:29:50 +0000] [49457] [INFO] Listening at: http://0.0.0.0:8000 (49457) [2021-09-27 01:29:50 +0000] [49457] [INFO] Using worker: sync [2021-09-27 01:29:50 +0000] [49459] [INFO] Booting worker with pid: 49459 [2021-09-27 01:29:50 +0000] [49460] [INFO] Booting worker with pid: 49460 [2021-09-27 01:29:50 +0000] [49457] [DEBUG] 2 workers
现在在浏览器中再次访问您网站的 URL。您仍然需要 8000 端口:
http://www.supersecure.codes:8000/myapp/
再次检查您的 VM 终端。您应该在 Gunicorn 的日志文件中看到如下一行或多行:
67.xx.xx.xx - - [27/Sep/2021:01:30:46 +0000] "GET /myapp/ HTTP/1.1" 200 182
这些行是访问日志,告诉您有关传入请求的信息:
为简洁起见,上面排除的是用户代理,它也可能出现在您的日志中。以下是 macOS 上 Firefox 浏览器的示例:
Mozilla/5.0 (Macintosh; Intel Mac OS X ...) Gecko/20100101 Firefox/92.0
随着 Gunicorn 的启动和聆听,是时候将合法的 Web 服务器引入到等式中了。
合并 Nginx
此时,您已将 Django 的runserver命令替换gunicorn为应用程序服务器。还有一个玩家要添加到请求链中:一个像Nginx这样的网络服务器。
等等——你已经添加了 Gunicorn!为什么你需要在图片中添加一些新的东西?之所以会这样,是因为 Nginx 和 Gunicorn 是两个不同的东西,它们是共存的,是一个团队。
Nginx将自己定义为高性能 Web 服务器和反向代理服务器。值得分解它,因为它有助于解释 Nginx 与 Gunicorn 和 Django 的关系。
首先,Nginx 是一个Web 服务器,因为它可以为 Web 用户或客户端提供文件。文件是文字文档:HTML、CSS、PNG、PDF——任你说。在过去,在 Django 等框架出现之前,网站的功能基本上是直接查看文件系统是很常见的。在 URL 路径中,斜杠表示服务器文件系统的有限部分上的目录,您可以请求查看这些目录。
请注意术语的细微差别:
Django 是一个网络框架。它使您可以构建核心 Web 应用程序,为网站上的实际内容提供支持。它处理 HTML 呈现、身份验证、管理和后端逻辑。
Gunicorn 是一个应用服务器。它将 HTTP 请求转换为 Python 可以理解的内容。Gunicorn 实现了Web 服务器网关接口 (WSGI),它是 Web 服务器软件和 Web 应用程序之间的标准接口。
Nginx 是一个网络服务器。它是公共处理程序,更正式地称为反向代理,用于传入请求并扩展到数千个同时连接。
Nginx 作为 Web 服务器的一部分作用是它可以更有效地服务静态文件。这意味着,对于图片等静态内容的请求,可以去掉Django这个中间人,让Nginx直接渲染文件。我们将在本教程的后面部分介绍这一重要步骤。
Nginx 也是一个反向代理服务器,因为它位于外部世界和您的 Gunicorn/Django 应用程序之间。与您可能使用代理发出出站请求的方式相同,您可以使用诸如 Nginx 之类的代理来接收它们:
要开始使用 Nginx,请安装它并验证其版本:
$ sudo apt-get install -y 'nginx=1.18.*' $ nginx -v # Display version info nginx version: nginx/1.18.0 (Ubuntu)
然后,您应该将您为端口 8000 设置的入站允许规则更改为端口 80。将入站规则替换为TCP:8000以下内容:
其他规则,例如 SSH 访问规则,应保持不变。
现在,启动nginx服务并确认其状态为running:
$ sudo systemctl start nginx $ sudo systemctl status nginx ● nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; ... Active: active (running) since Mon 2021-09-27 01:37:04 UTC; 2min 49s ago ...
现在您可以向一个看起来很熟悉的 URL 发出请求:
http://supersecure.codes/
与您之前的情况相比,这是一个很大的不同。URL 中不再需要端口 8000。相反,端口默认为端口 80,看起来更正常:
这是 Nginx 的一个友好特性。如果您以零配置启动 Nginx,它会为您提供一个页面,表明它正在侦听。现在尝试/myapp以下 URL 中的页面:
http://supersecure.codes/myapp/
记得替换supersecure.codes成自己的域名。
您应该会看到 404 响应,这没关系:
这是因为您/myapp通过端口 80请求路径,这是 Nginx 而不是 Gunicorn 正在侦听的地方。此时,您有以下设置:
Nginx 正在侦听端口 80。
Gunicorn 正在单独侦听端口 8000。
在您指定之前,两者之间没有联系或联系。Nginx 不知道 Gunicorn 和 Django 有一些他们希望世界看到的甜蜜 HTML。这就是它返回404 Not Found响应的原因。您还没有设置它来代理对 Gunicorn 和 Django 的请求:
您需要为 Nginx 提供一些基本配置,以告诉它将请求路由到 Gunicorn,然后 Gunicorn 会将它们提供给 Django。打开/etc/nginx/sites-available/supersecure并添加以下内容:
server_tokens off; access_log /var/log/nginx/supersecure.access.log; error_log /var/log/nginx/supersecure.error.log; # This configuration will be changed to redirect to HTTPS later server { server_name .supersecure.codes; listen 80; location / { proxy_pass http://localhost:8000; proxy_set_header Host $host; } }
请记住,您需要supersecure将文件名替换为您站点的主机名,并确保将 的server_name值替换为.supersecure.codes您自己的域,并以点为前缀。
注意:您可能需要sudo打开/etc.
这个文件就是Nginx 反向代理配置的“Hello World” 。它告诉 Nginx 如何表现:
在端口 80 上侦听使用主机supersecure.codes及其子域的请求。
将这些请求传递给http://localhost:8000Gunicorn 正在监听的地方。
该proxy_set_header领域是非常重要的。它确保 Nginx 将Host最终用户发送的HTTP 请求标头传递给 Gunicorn 和 Django。Nginx 将Host: localhost默认使用,忽略Host最终用户浏览器发送的标头字段。
您可以使用nginx configtest以下方法验证您的配置文件:
$ sudo service nginx configtest /etc/nginx/sites-available/supersecure * Testing nginx configuration [ OK ]
的[ OK ]输出表示配置文件是有效的,并且可以进行解析。
现在您需要将此文件符号链接到sites-enabled目录,替换supersecure为您的站点域:
$ cd /etc/nginx/sites-enabled $ # Note: replace 'supersecure' with your domain $ sudo ln -s ../sites-available/supersecure . $ sudo systemctl restart nginx
在使用 向您的站点发出请求之前httpie,您需要再添加一个入站安全规则。添加以下入站规则:
此安全规则允许来自 VM 本身的公共(弹性)IP 地址的入站 HTTP 流量。起初这似乎有点过分,但您需要这样做,因为现在请求将通过公共 Internet 路由,这意味着使用安全组 ID 的自引用规则将不再足够。
现在它使用 Nginx 作为 Web 服务器前端,重新向站点发送请求:
$ GET http://supersecure.codes/myapp/ HTTP/1.1 200 OK Connection: keep-alive Content-Encoding: gzip Content-Type: text/html; charset=utf-8 Date: Mon, 27 Sep 2021 19:54:19 GMT Referrer-Policy: same-origin Server: nginx Transfer-Encoding: chunked X-Content-Type-Options: nosniff X-Frame-Options: DENY
Now this is some sweet HTML!
既然 Nginx 位于 Django 和 Gunicorn 的前面,这里有一些有趣的输出:
Nginx 现在返回Server标头为Server: nginx,表明 Nginx 是新的前端 Web 服务器。设置server_tokens为 的值会off告诉 Nginx 不要发出其确切版本,例如nginx/x.y.z (Ubuntu). 从安全角度来看,这会泄露不必要的信息。
Nginxchunked用于Transfer-Encoding标头而不是广告Content-Length。
Nginx 还要求保持与Connection: keep-alive.
接下来,您将利用 Nginx 的核心功能之一:快速有效地提供静态文件的能力。
直接使用 Nginx 提供静态文件
您现在可以将 Nginx 代理请求发送到您的 Django 应用程序。重要的是,您还可以使用 Nginx直接提供静态文件。如果您有DEBUG = Truein project/settings.py,那么 Django 将呈现文件,但这非常低效且可能不安全。相反,您可以让您的 Web 服务器直接呈现它们。
静态文件的常见示例包括本地 JavaScript、图像和 CSS — 任何不需要 Django 作为等式的一部分来动态呈现响应内容的地方。
首先,从您的项目目录中,创建一个位置来保存和跟踪开发中的 JavaScript 静态文件:
$ pwd /home/ubuntu/django-gunicorn-nginx $ mkdir -p static/js
现在打开一个新文件static/js/greenlight.js并添加以下 JavaScript:
// Enlarge the #changeme element in green when hovered over (function () { "use strict"; function enlarge() { document.getElementById("changeme").style.color = "green"; document.getElementById("changeme").style.fontSize = "xx-large"; return false; } document.getElementById("changeme").addEventListener("mouseover", enlarge); }());
如果将鼠标悬停在此 JavaScript 上,它将使文本块以绿色大字体爆炸。是的,这是一些前沿的前端工作!
接下来,将以下配置添加到project/settings.py,更新STATIC_ROOT为您的域名:
STATIC_URL = "/static/" # Note: Replace 'supersecure.codes' with your domain STATIC_ROOT = "/var/www/supersecure.codes/static" STATICFILES_DIRS = [BASE_DIR / "static"]
您告诉 Django 的collectstatic命令在哪里搜索和放置从多个 Django 应用程序(包括 Django 自己的内置应用程序,例如admin.
最后但并非最不重要的是,修改 HTMLmyapp/templates/myapp/home.html以包含您刚刚创建的 JavaScript:
Now this is some sweet HTML!
这确实是一些甜蜜的 HTML。
结论
如果您已经按照本教程进行操作,那么您的站点与之前的独立开发 Django 应用程序相比,已经取得了很大的进步。您已经了解了 Django、Gunicorn 和 Nginx 如何结合在一起来帮助您安全地服务于您的站点。
在本教程中,您学习了如何:
将您的 Django 应用程序从开发带到生产
在现实世界的公共域上托管您的应用程序
将Gunicorn和Nginx引入请求和响应链
使用HTTP 标头来提高站点的 HTTPS 安全性
您现在有一组可重现的步骤来部署您的生产就绪 Django Web 应用程序。
您可以通过以下链接下载本教程中使用的 Django 项目:
进一步阅读
有了站点安全性,您永远无法 100% 到达那里,这是一个现实。您总是可以添加更多功能来进一步保护您的站点并生成更好的日志信息。
查看以下链接,了解您可以自行采取的其他步骤:
Django:部署清单
Mozilla :网络安全
Gunicorn :部署 Gunicorn
Nginx:使用Forwarded标题
Adam Johnson:如何在您的 Django 网站上为安全标头评分 A+
Django https Nginx
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。