2011-11-05 69 views
73

我有一個應用程序使用「安全」Cookie並希望測試它的功能,而無需設置複雜的啓用SSL的開發服務器。有沒有辦法做到這一點,就像我可以使用./manage.py runserver測試非加密請求一樣簡單?如何使用'runserver'輕鬆測試與Django的https連接?

+0

難道你不能只是指定運行服務器443,使服務器端口443上運行? – Furbeenator

+0

@Furbeenator:不幸的是 - 這隻會使443服務器HTTP,我需要的是一個實際的SSL服務器運行。 –

回答

97

這不是作爲作爲內置開發服務器很簡單,但使用stunnel作爲瀏覽器和開發服務器之間的SSL化中間人來關閉它並不難。 Stunnel允許您在您的機器上設置一個輕量級服務器,該服務器接受配置端口上的連接,將它們封裝在SSL中,並將它們傳遞給其他服務器。我們將使用它來打開一個stunnel端口(8443),並將它接收到的任何流量傳遞給一個Django runserver實例。

首先,您需要stunnel,它可以是downloaded here或可能由您的平臺的包系統提供(例如:apt-get install stunnel)。我將使用stunnel的第4版(例如:Ubuntu上的/usr/bin/stunnel4),版本3也可以工作,但具有不同的配置選項。

首先在您的Django項目中創建一個目錄,以保存必要的配置文件和SSLish內容。

mkdir stunnel 
cd stunnel 

接下來我們需要創建一個本地證書和用於SSL通信的密鑰。爲此我們轉向openssl。

打造關鍵:

openssl genrsa 1024 > stunnel.key 

創建一個使用該密鑰的證書(這會問你的信息一大堆,將被列入certficate - 只是什麼感覺很好,你回答):

openssl req -new -x509 -nodes -sha1 -days 365 -key stunnel.key > stunnel.cert 

現在將這些成安全通道將用於其SSL通信的單個文件:

cat stunnel.key stunnel.cert > stunnel.pem 

創建安全通道稱爲dev_https具有以下內容的配置文件:

pid= 

cert = stunnel/stunnel.pem 
sslVersion = SSLv3 
foreground = yes 
output = stunnel.log 

[https] 
accept=8443 
connect=8001 
TIMEOUTclose=1 

該文件會告訴安全通道它所需要知道的。具體而言,你告訴它不要使用pid文件,證書文件的位置,使用哪個版本的SSL,它應該在前臺運行,應該在哪裏記錄其輸出,並且它應該接受端口上的連接8443並將它們一起傳送到端口8001.最後一個參數(TIMEOUTclose)指示它在1秒鐘過去後自動關閉連接,而沒有任何活動。

現在彈出備份到你的Django項目目錄(一個與它manage.py):

cd .. 

這裏,我們將創建一個腳本名爲runserver命令,將運行安全通道和兩個Django開發服務器(一個正常的連接,以及一個用於SSL連接):

stunnel4 stunnel/dev_https & 
python manage.py runserver& 
HTTPS=1 python manage.py runserver 8001 

讓我們打破這,行由行:

  • 第1行:啓動stunnel並將其指向我們剛剛創建的配置文件。這具有安全通道監聽端口8443,它包接收SSL的任何連接,並通過他們對端口8001
  • 第2行:開始進行正常的Django的runserver實例(在端口8000)
  • 第3行:啓動另一個的Django的runserver實例(在端口8001上)並將其配置爲將所有傳入連接視爲正在使用HTTPS執行。當你想運行您的開發服務器從你的項目目錄只執行./runserver

    chmod a+x runserver 
    

    現在:

讓我們剛剛創建可執行文件,文件的runScript。要試用它,只需將瀏覽器指向http://localhost:8000即可獲得正常的HTTP流量,而將https://localhost:8443指向HTTPS流量即可。請注意,您的瀏覽器幾乎肯定會抱怨所使用的證書,並要求您添加例外或明確指示瀏覽器繼續瀏覽。這是因爲您創建了自己的證書,並且瀏覽器不信任它來說明它是誰的真相。這對開發很好,但顯然不會削減生產。

不幸的是,在我的機器上,當我點擊Ctrl-C時,這個runserver腳本不會很好地退出。我必須手動殺死進程 - 任何人都有建議來解決這個問題?

感謝Michael Gile的post和django-weave的wiki entry作爲參考材料。

+3

我只是偶然發現了這個答案。一些說法:你不一定需要在8001上運行一個獨立的開發實例,你可以讓它連接到8000端口。如果你想讓stunnel自動被殺死,添加一個函數和一個退出陷阱:kill_stunnel(){ kill $ stunnel_pid} trap kill_stunnel exit stunnel4 stunnel/dev https&stunnel_pid = $ 1 – Friek

+2

第二個實例是用HTTPS = 1調用的,這意味着'request.is_secure()'會報告'True'。如果你不需要,那麼你是對的 - 你可以在單個實例中指出stunnel。 –

+0

如果你遇到stunnel fips模式不支持....添加fips = no到dev_https文件關掉它 – yeahdixon

1

它可以在一個行完成與socat:

socat openssl-listen:8443,fork,reuseaddr,cert=server.pem,verify=0 tcp:localhost:8000 

,其中8443是端口偵聽傳入的HTTPS連接,server.pem是自簽名的服務器證書和本地主機:8000是一個調試像往常一樣啓動HTTP服務器。

更多細節:http://www.dest-unreach.org/socat/doc/socat-openssltunnel.html

9

註冊到https://ngrok.com/。您可以使用https進行測試。這可能會幫助那些只想快速測試https的人。

+0

爲了快速測試,這是一個很好的解決方案。我沒有註冊任何東西,只需下載並運行./ngrok http 8000,8000是我的localhost端口。 – GavKilbride

61

我會推薦使用django-sslserver包。

PyPI上的當前包僅支持Django版本1.5.5,但補丁已通過5d4664c提交。通過此修復,系統運行良好,並且是測試https連接的非常簡單直接的解決方案。

更新: 由於我發佈了我的答案,上面的提交已被merged添加到主分支中,並且新的release已被推送到PyPI。因此,不應該有任何需要爲該特定修補程序指定5d4664c提交。

+5

這看起來很有希望 - 我可能必須更新這一個接受的答案。其他人想要稱重? –

+1

剛剛嘗試過,像1.7c1上的魅力一樣。雖然我都是爲了有趣的答案,但這只是完成它。如果django-sslserver軟件包不再更新,那麼stunnel解決方案很好。 +1這個答案。 – Plastefuchs

+3

這應該成爲公認的答案,在一個相當複雜的項目中使用了一段時間,如果不在https上運行並且從未出現問題,該項目根本無法工作。 –

4

對於那些尋找安全通道選項用於調試目的的前景化版本:

stunnel.pem是生成的證書在埃文格林頂級投回答。

偵聽端口443上所有的本地接口,並轉發到端口80上的本地主機

sudo stunnel -f -p stunnel.pem -P ~/stunnel.pid -r localhost:80 -d 443 

須藤僅供傳入端口必要(-d [主持人:]端口)1024

35

到類似下Django的sslserver你可以使用RunServerPlusdjango-extensions

它有WERKZEUG(這樣你就可以訪問到優秀WERKZEUG調試器)和pyOpenSSL(僅用於SSL模式)的依賴,從而安裝運行:

pip install django-extensions Werkzeug pyOpenSSL 

將它添加到INSTALLED_APPS在項目settings.py文件:

INSTALLED_APPS = (
    ... 
    'django_extensions', 
    ... 
) 

然後你可以運行在SSL模式下的服務器:

./manage.py runserver_plus --cert /tmp/cert 

這將創建一個證書文件在/tmp/cert.crt和一個密鑰文件在/tmp/cert.key,然後可以重複使用未來的會議。

在django擴展中包含一些額外的東西,你可能會發現它的使用,所以值得快速瀏覽文檔。

+1

其實Django 1.6+的最佳答案,因爲django-sslserver不支持自動重新加載新版本 – Zat42