Web 開發學習筆記(4) --- 重定向與HSTS

回顧

  • 經過前幾篇文章的內容, 咱們已經搭建了基於 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 Code301 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學習筆記.


參考資料

相關文章
相關標籤/搜索