使用 Gunicorn、Nginx 和 HTTPS 安全地部署 Django 應用程序

      網友投稿 1287 2025-03-31

      目錄

      從 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/.pem ubuntu@

      此命令將您以用戶身份登錄到您的 VM?ubuntu。這里~/.ssh/.pem是私鑰的路徑,它是您綁定到 VM 的一組安全憑證的一部分。VM 是 Django 應用程序代碼所在的位置。

      有了這個,您應該已經準備好繼續構建您的應用程序了。

      創建一個 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 頁面:

      My secure app

      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 &執行command,以便您可以繼續使用您的 shell。您可以使用jobs -l查看進程標識符 (PID),它可以讓您將進程帶到前臺或終止它。nohup將標準輸出 (stdout)和標準錯誤 (stderr)重定向到文件nohup.out.

      注意:如果它出現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 My secure app

      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,您應該看到如下所示的內容:

      [] "GET /myapp/ HTTP/1.1" 200 182

      恭喜,您剛剛邁出了創建自己網站的里程碑式的第一步!但是,在這里暫停并注意 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 服務器前端,重新向站點發送請求:

      使用 Gunicorn、Nginx 和 HTTPS 安全地部署 Django 應用程序

      $ 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 My secure app

      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:

      My secure app

      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小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:制造生產的區別與聯系(制造生產的區別與聯系是什么)
      下一篇:ERP如何滿足各種制造業的需求?
      相關文章
      亚洲综合丁香婷婷六月香| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 亚洲一区二区三区乱码A| 亚洲成AV人片在WWW| 亚洲中文字幕无码亚洲成A人片| 67pao强力打造67194在线午夜亚洲| 久久久久久久尹人综合网亚洲| 亚洲情综合五月天| 曰韩亚洲av人人夜夜澡人人爽| 亚洲国产91精品无码专区| 亚洲国产成人爱av在线播放| 亚洲国产精品狼友中文久久久 | 亚洲成在人线aⅴ免费毛片| 亚洲男同gay片| 亚洲AV综合色区无码一二三区| 中文字幕在线观看亚洲视频| 国产成人精品日本亚洲网址 | 国产成人亚洲综合无码| 日韩亚洲变态另类中文| 亚洲区小说区图片区QVOD| 亚洲大尺度无码专区尤物| 久久99国产亚洲精品观看| 久久亚洲日韩精品一区二区三区| 亚洲最大的成网4438| 亚洲日韩中文字幕| 亚洲欧洲日韩极速播放 | 亚洲AV午夜成人片| 亚洲一区免费观看| 亚洲女人初试黑人巨高清| 亚洲国产日韩视频观看| 亚洲精品久久无码av片俺去也| 日韩国产欧美亚洲v片| 在线观看亚洲电影| 久久精品国产亚洲精品| 国产AV无码专区亚洲AV毛网站 | jizzjizz亚洲日本少妇| 亚洲精品无码永久在线观看 | 亚洲乱码无码永久不卡在线| 久久精品国产亚洲av麻| 亚洲经典在线中文字幕| 狠狠色香婷婷久久亚洲精品|