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学习笔记.


参考资料

相关文章
相关标签/搜索