经过前几篇文章的内容, 咱们已经搭建了基于 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学习笔记.