當前位置:
首頁 > 知識 > Flask 進階:如何實現 HTTPS?

Flask 進階:如何實現 HTTPS?

作者:劉利強

來源:作者投稿

今天看到光頭哥更新的最新一篇博文:Running Your Flask Application Over HTTPS,雖然他講的是如何改進配置使用更安全的 Https 服務,然而我更感興趣的是其中的一段:

以前印象中看過 Flask 是原生支持 ssl 的,但是當時沒怎麼在意,今天突然來了興趣,在想 Flask 是如何實現的,所以就扒了一下源碼,發現關鍵不在於 Flask,還是它的底層包:Werkzeug,所以就繼續看看 Werkzeug 的源碼,看下具體是如何實現的,為了簡化一下源碼解析,直接從 Werkzeug 如何提供 Https 服務建起。

使用 Werkzeug 創建 Https 伺服器

這裡其實有個前提沒有介紹,那就是讀者可能需要有一些關於 Https 的基礎知識,如果沒有的話,可以想看一下 wiki 中關於 https 的內容了解一下背景,然後再繼續。

生成 https 證書

在創建一個 https 伺服器之前,我們需要先生成一份證書,對於生產環節的證書都是需要驗證過的,但是對於我們實驗的話,那就隨便了,這裡我有一個簡單的代碼可以生成證書,可以直接拿來使用:

執行之後,我們就可以在指定的目錄下看到證書和公鑰了,默認的路徑是:

看到這些我們就可以確認我們的證書和公鑰是生成好了,可以進行下一步了。

創建 Werkzeug https 伺服器

關於 Werkzeug ,在我的博客之前寫過一篇介紹的文章,感興趣的同學可以先看一下:werkzeug初級指導;這裡就不多做累贅了,直接給出一份我寫的簡單伺服器代碼:

出於我的習慣,我平時都是編寫一份啟動腳本的,這裡也一併給出來:

執行 之後我們應該可以看到一些 Log,然後嘗試訪問一下,我這裡的配置都在 run.sh 裡面了,所以訪問的時候就直接訪問: ,但是,可以在 chrome 中發現有警報:

當然,這個警告是正常的,因為之前說了,這個證書是未授權的,所以會警報,這裡也不延伸如何解決這種警告(根本性解決),我們可以選擇高級選項選擇信任並且打開,你講可以成功訪問這個伺服器:

這個例子只是想演示一下如何使用 Werkzeug 創建一個 https 伺服器,並且是能夠訪問成功的,但是咱們的正事是探究 Werkzeug 是如何實現的。接下來,將以這個例子進行深入,看看 Werkzeug 的實現原理。

Werkzeug 實現

截止至寫這篇文章的時候,Werkzeug 最新的穩定版本是0.12.1,所以源碼就以 這個版本為例進行閱讀。基於剛才的 Demo 代碼,我們忽略前面創建 WSGI 引用的過程,直接看關鍵的一行,其實也就這行是真正和 https 相關的,所以我們就以這行為出發點,進行深入:

在 werkzeug 的源代碼: 中我們可以看到 的源代碼:

這裡忽略了很多代碼,同時因為工具限制,代碼行數後續有點混亂,但是,無妨,不影響閱讀,最後有兩行是標紅的,其實這兩行也就是 的核心代碼了,為了簡單,我們就以 看,那麼,其實 的代碼就可以簡約成這樣:

寥寥幾行代碼,所以我們一下子就看出來了,核心還得看 這個函數的實現,所以毫不猶豫得就跟進去了,位置在 line: 534 處,代碼也是異常簡單,為了方便閱讀,我也做了一個簡化,簡化之後就成了:

很好,這裡又多了一個新東西,那就是 ,這個到底是啥呢,讓我們跟進去看看,位置還是在 中,line 446,簡化之後可以看成:

一目了然,我們可以發現其實這就是一個 Python 自帶的 HTTPServer 的子類,然後再細看一下,其實這就是 Python 原生實現 https 伺服器的簡單實現了,到此可以終止了。

從這一條線我們可以看到,其實 Flask 或者說 Werkzeug 實現 https 還是在原生 HTTPServer 的基礎上簡單做了一些封裝實現的,並沒有做關於 ssl 的特殊處理,所以用的時候我們需要記住這個實現原理就可以定位很多問題了。

被忽略掉的東西

在第二部分的實現中,我們簡化了不少代碼,現在,我們理清了代碼的思路之後,就回過頭來看看被我們忽略掉的有價值的東西。

DEBUG 模式是如何實現的

在使用 Flask 的時候,有個很有趣的功能就是當我們在調用 的時候加上個參數 就是 DEBUG 模式了,那麼它是如何實現的呢?

首先,我想了想,DEBUG 模式和非 DEBUG 模式的區別是啥,好像很少,但是細細數一下好像又很多,例如:

還有很多的差別,那麼這些差別都是如何實現的捏?看一下代碼,可以在 line 632 中看到 WSGI app 對象被包裝了一層,包裝類是: ,源碼位置在 line 228 處,其中微妙之處在於line 437,這裡其實就是處理各種 DEBUG 特性的地方:

DEBUG 模式的時候異常是跳到異常的 html 頁面,而非 DEBUG 模式直接 500 了

DEBUG 模式的時候 log 信息比非 DEBUG 模式多了很多,應該是列印級別降低了

DEBUG 模式的時候還支持在前端頁面上調試代碼

靜態文件處理

在我們的 DEMO 代碼裡面,有一段關於靜態文件的代碼,可以簡單明了得看到靜態文件是通過中間件的方式實現的,而內部的具體實現則是通過匹配 url 的前綴是否是靜態文件的前綴實現的,簡化只則為:

重用描述符?

werkzeug/serving.py的 函數中,有一段被我忽略了,原來是這樣的:

之後跟進 之後可以發現 是這樣被使用的:

卧槽,居然還可以這樣,跟了一下 的源代碼,可以發現 ,然後 中的 是繼承自 的,在 中是這麼用的

查看一下 的文檔可以發現:

select.select(rlist, wlist, xlist[, timeout]) This is a straightforward interface to the Unix select() system call. The first three arguments are sequences of 『waitable objects』: either integers representing file descriptors or objects with a parameterless method named fileno() returning such an integer:

所以繼續往下看可以發現 的代碼中有這麼一段:

所以,可以看到,剛才那段替換居然是可以的!!!

更多的點

這篇文章已經寫很多了,留個坑吧,下次接著寫,可以發現這裡還是有很多知識是平時不常用的,但是很有意思。

Tips

本文中涉及的 DEMO 代碼可以在 Github 中查看:Werkzeug https Demo

Reference

HTTPS Wiki

Running Your Flask Application Over HTTPS

How to serve HTTPSdirectlyfrom Flask

werkzeug 初探

Creating an HTTPS server in Python

Python select funciton docs

題圖:pexels,CC0 授權。

點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 編程派 的精彩文章:

這裡有一張騰訊技術大會的門票,先到先得
如何構建一個分布式爬蟲:實戰篇
如何構建一個分布式爬蟲:基礎篇
裝扮你的 Jupyter Notebook
微信紅包海量性能背後的秘密

TAG:編程派 |

您可能感興趣

實例分割的進階三級跳:從 Mask R-CNN 到 Hybrid Task Cascade
Zante,NB的進階,NB Fresh Foam Zante Pursuit跑鞋
Find回歸與OPPO的進階
APICloud開發者進階之路:APICloud擴展模塊
Xcode 9—進階的 iOS Simulator
macOS 效率進階,學習如何用 AppleScript 實現自動化
入門進階佳品——TANCHJIM Darkside開箱簡評
這份歌單告訴你,為何 Lil Skies 的音樂是 Emo Rap 的新進階
TUMI Georgica系列,你的魅力進階新攻略
TensorFlow 入門進階
Windows PowerShell進階 理解Module
Windows PowerShell進階比較2個csv的差異
PyTorch進階之路(二):如何實現線性回歸
尚臻品質進階之路又一里程碑:Family-Friendly Residential Complex of the Year
耳機發燒友入門進階佳品——TANCHJIM Darkside開箱簡評
Vasyli Medical 進階足踝治療
買買買的進階版,便是收藏家了——Hillwood Estate Museum and Garden
Colourpop出了12星座專屬眼影盤?YOHO!GIRL進階版來了!
Kaggle 大神 Eureka 的高手進階之路
菜雞進階路之 Debounce&LazyFunction