资讯专栏INFORMATION COLUMN

Web 开发学习笔记(4) --- 重定向与HSTS

kevin / 1705人阅读

摘要:回顾通过前几篇文章的内容我们已经搭建了基于框架的一个简单的应用的代码如下此外我们还为其申请了公网和域名并且部署了的证书现在当我们在浏览器地址栏输入即可访问我们的网站不过我们的网站目前还存在几个问题无法访问每次都需要用户手动输入前缀以制定形式

回顾

通过前几篇文章的内容, 我们已经搭建了基于 Flask 框架的一个简单的 Web 应用, server.py 的代码如下


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 即可访问我们的网站.


不过, 我们的网站目前还存在几个问题:


1.无法访问 http://www.awesome.com
2.每次都需要用户手动输入 https:// 前缀以制定 https 形式的访问

为此, 我们需要重新编写一个 server 并监听 80 端口, 并对所有请求返回一个 redirect 响应, 把所有 http 请求都重定向为 https 请求. 最后, 我们还将开启 HSTS, 方便用户、提高安全性的同时减少无效的访问.


监听 80 端口

考虑我们的目的只是为了进行重定向, 我们不如暂且撇开 Flask, 用 Python 自带的网络库写一个简单的 server, 把它当成一个练手的 demo.


结合文档 wsgiref, 我们可以新建 ~/webapp/redirect.py 并填写如下内容


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
" % (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 的内容


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


参考资料

wsgiref — WSGI Utilities and Reference Implementation, Python Docs

how-to-redirect-http-to-https-in-flask, Stack Overflow

HSTS学习笔记

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/43196.html

相关文章

  • HSTS进一步增强网站安全性

    摘要:网站可以选择使用策略,来让浏览器强制使用与网站进行通信,以减少会话劫持风险。谷歌想出了一个办法把想启用的所有站点的域名预先写进浏览器代码不就好了。谷歌维护了一个名为的网站,专门用于申请让浏览器给各站点内置开启支持。 由于 Lets Encrypt 等免费证书的存在,各位站长都可以很容易的加固自己的网站。然而 HTTPS 不是万能药,并不是加入 HTTPS 支持就万事大吉了。 譬如说,就...

    cuieney 评论0 收藏0
  • HSTS进一步增强网站安全性

    摘要:网站可以选择使用策略,来让浏览器强制使用与网站进行通信,以减少会话劫持风险。谷歌想出了一个办法把想启用的所有站点的域名预先写进浏览器代码不就好了。谷歌维护了一个名为的网站,专门用于申请让浏览器给各站点内置开启支持。 由于 Lets Encrypt 等免费证书的存在,各位站长都可以很容易的加固自己的网站。然而 HTTPS 不是万能药,并不是加入 HTTPS 支持就万事大吉了。 譬如说,就...

    zilu 评论0 收藏0
  • HTTP 状态码

    摘要:状态码有哪些一般大家都知道页面不存在,服务器错误,重定向,临时重定向,,未授权啥的。总结仅仅三个状态码,都可以牵涉到如此丰富的知识,对于状态码,我们不能只是片面的去背诵状态码及对应的含义,要去主动挖掘,深入,借助状态码来建立自己的网络体系。 之前写的一些笔记,简单记录在这里。 http状态码有哪些? 一般大家都知道404页面不存在,500服务器错误,301重定向,302临时重定向,2...

    yuanzhanghu 评论0 收藏0
  • Web 开发学习笔记(3) --- 申请和部署HTTPS证书

    摘要:简介现在已经进入的时代证书目前应用广泛发展迅速相较于明文传输的更加安全即由于其安全层使用的是因此也可以称为或关于证书的分类可以参考这篇博客证书需要向国际公认的证书证书认证机构申请接下来我们将使用自动化证书管理工具为我们的域名申请颁发的证书然 简介 现在已经进入 HTTPS 的时代, HTTPS 证书 目前应用广泛, 发展迅速. 相较于明文传输的 HTTP, HTTPS 更加安全. ...

    gekylin 评论0 收藏0
  • Web 应用安全性: 使用这些 HTTP 头保护 Web 应用

    摘要:综上所述,认为没有提供的保护,用户会过得更好安全研究人员并不完全反对这一决定。内容安全策略是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本和数据注入攻击等。 这是关于web安全性系列文章的第 三 篇,其它的可点击以下查看: Web 应用安全性: 浏览器是如何工作的 Web 应用安全性: HTTP简介 目前,浏览器已经实现了大量与安全相关的头文件,使攻击者更难利用漏...

    spademan 评论0 收藏0

发表评论

0条评论

kevin

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<