經過前幾篇文章的內容, 咱們已經搭建了基於 Flask
框架的一個簡單的 Web
應用, server.py
的代碼以下html
from flask import Flask from flask.views import MethodView app = Flask(__name__) class IndexHandler(MethodView): def __init__(self, name): print(name) def get(self): return 'It is a GET request' def post(self): return 'It is a POST request' if __name__ == '__main__': app.add_url_rule('/', view_func=IndexHandler.as_view('index')) context = ('./server.cer', './server.key') app.run(port=443, host='0.0.0.0', debug=True, threaded=True, ssl_context=context)
此外, 咱們還爲其申請了公網 IP 和域名 www.awesome.com
, 而且部署了 Let's Encrypt 的 HTTPS 證書. 如今, 當咱們在瀏覽器地址欄輸入 https://www.awesome.com
便可訪問咱們的網站.python
不過, 咱們的網站目前還存在幾個問題:git
1.沒法訪問 http://www.awesome.com 2.每次都須要用戶手動輸入 https:// 前綴以制定 https 形式的訪問
爲此, 咱們須要從新編寫一個 server
並監聽 80
端口, 並對全部請求返回一個 redirect
響應, 把全部 http
請求都重定向爲 https
請求. 最後, 咱們還將開啓 HSTS
, 方便用戶、提升安全性的同時減小無效的訪問.github
80
端口考慮咱們的目的只是爲了進行重定向, 咱們不如暫且撇開 Flask
, 用 Python
自帶的網絡庫寫一個簡單的 server
, 把它當成一個練手的 demo.web
結合文檔 wsgiref, 咱們能夠新建 ~/webapp/redirect.py
並填寫以下內容flask
from wsgiref.util import setup_testing_defaults from wsgiref.simple_server import make_server def simple_app(environ, start_response): status = '200 OK' headers = [('Content-type', 'text/plain; charset=utf-8')] start_response(status, headers) ret = [("%s: %s\n" % (key, value)).encode("utf-8") for key, value in environ.items()] return ret with make_server('0.0.0.0', 80, simple_app) as httpd: httpd.serve_forever()
http
請求重定向爲 https
請求爲了實現重定向(redirect
), 咱們須要構造這樣一個 http response
:瀏覽器
Status Code
是 301 Moved Permanently
headers
中包含了 redirect 的目標地址 Location: https://...
, 其中 ... 是用戶請求的 URI
, 如首頁的 URI
就是 https://www.awesome.com/
, 下面以這個 URI
爲例.response body
設爲空便可所以咱們能夠獲得這樣的 response headers
安全
HTTP/1.1 301 Moved Permanently Content-length: 0 Location: https://www.awesome.com/
咱們能夠據此修改 redirect.py
的內容bash
from wsgiref.util import request_uri from wsgiref.simple_server import make_server def simple_app(environ, start_response): uri = request_uri(environ) # 獲取 client 請求的地址 URI location = uri[:4] + 's' + uri[4:] # 將 http 替換成 https status = '301 Moved Permanently' # 設置 Status Code headers = [ ('Content-length', '0'), ('Location', location) ] # 設置 headers start_response(status, headers) return b'' httpd = make_server('0.0.0.0', 80, simple_app) httpd.serve_forever()
至此, 咱們新編寫的 server
已經完成了, 咱們在 ~/webapp/
目錄下打開一個 Terminal
, 而後運行以下命令網絡
python3 redirect.py
接着, 咱們打開瀏覽器的開發者工具, 並在地址欄輸入 www.awesome.com
. 若是一切順利, 咱們將在開發者工具中看到一個 301
跳轉, 而後被重定向到 https://www.awesome.com
HSTS
爲了開啓 HSTS
, 咱們須要在 http response headers
中添加以下記錄
Strict-Transport-Security: max-age=15768000; includeSubDomains; preload
以上內容在提供 https
服務的 server
中添加便可, 所以咱們須要修改 ~/webapp/server.py
. 首先引入 make_response
, 而後在 get()
方法中生成 resp = make_response('It is a GET request')
, 以替換原來的生成響應的方法. 接着加上新的 headers
記錄 resp.headers['Strict-Transport-Security']
. 所以能夠獲得以下 server.py
from flask import Flask, make_response from flask.views import MethodView app = Flask(__name__) class IndexHandler(MethodView): def get(self): resp = make_response('It is a GET request') resp.headers['Strict-Transport-Security'] = 'max-age=15768000; includeSubDomains; preload' return resp if __name__ == '__main__': app.add_url_rule('/', view_func=IndexHandler.as_view('index')) context = ('./server.cer', './server.key') app.run(port=443, host='0.0.0.0', debug=True, threaded=True, ssl_context=context)
保存 server.py
以後, 咱們運行 server.py
python3 server.py
接着, 咱們用無痕模式訪問 www.awesome.com
, 在開發者工具中, 咱們首先能夠看到一個 301
跳轉, 而後在自動進行的對 https://www.awesome.com
的請求以後, 咱們就能夠在 response headers
看到新添加的 Strict-Transport-Security
記錄了.
此時, 若是咱們再次輸入 www.awesome.com
, 從開發者工具中咱們能夠看到, 跳轉碼從 301
變成了 307
, 也就是 Internal Redirect
, 這是在瀏覽器內部進行的重定向, 瀏覽器直接幫咱們在本地把 http
換成了 https
, 而不須要通過咱們的 redirect.py
, 減小了一次沒必要要的訪問. 這也是 HSTS
帶來的好處之一.
http response headers
中加入 HSTS
. 若是想了解更多關於 HSTS
的內容, 能夠參考這篇博客: HSTS學習筆記.