Flaskでヘッダー情報をafter_requestで設定する

after_requestが便利だと気がついてしまいました。

1

初期状態でのヘッダー確認

公式に紹介されている最小限のアプリケーション[*1]は以下のようになります。

from flask import Flask


app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

サーバを開始します。デフォルトではhttp://127.0.0.1:5000が使用されます。

この時のサイトのヘッダー情報をrequestsを使って確認します。

import requests


headers = requests.get('http://127.0.0.1:5000').headers
print(headers)
% {'Server': 'Werkzeug/2.1.2 Python/3.10.0', 'Date': 'Thu, 02 Jun 2022 11:30:54 GMT', 'Content-Type': 'text/html; charset=utf-8', 'Content-Length': '20', 'Connection': 'close'}

必要最低限の情報が登録されています。

2

after_request

試しに Content Security Policy (CSP) を登録します。

...

@app.after_request
def after_request(response):
    response.headers['Content-Security-Policy'] = "default-src 'self'" 
    return response

...
% {'Server': 'Werkzeug/2.1.2 Python/3.10.0', 'Date': 'Thu, 02 Jun 2022 11:49:22 GMT', 'Content-Type': 'text/html; charset=utf-8', 'Content-Length': '20', 
'Content-Security-Policy': "default-src 'self'", 'Connection': 'close'}

しっかりとCSPが登録されていることが確認できます。


Flaskの公式サイトにもあるようにセキュリティに関していくつか設定が必要になるケースがあります。[*2]

なので、updateを使って一気に登録するのが楽です。

...

security_headers = {
    'Strict-Transport-Security':
        'max-age=63072000; includeSubDomains; preload',
    'Content-Security-Policy':"default-src 'self'",
    'X-Content-Type-Options':'nosniff',
    'X-Frame-Options':'SAMEORIGIN',
    'X-XSS-Protection':'1; mode=block'
}

@app.after_request
def after_request(response):
    response.headers.update(security_headers)
    return response

...
3

おまけ

よくあるresponse.header

個人的には、Response.headerの形での登録をよく見る気がします。

例えば、Flask.make_responseを使う形です。

from flask import Flask, make_response


app = Flask(__name__)

@app.route("/")
def hello_world():
    response = make_response("<p>Hello, World!</p>")
    response.headers['Content-Security-Policy'] = "default-src 'self'"
    return response

問題はありませんが、after_requestの方が楽です。


@content_security_policy.setter

継承元のwerkzeug.sansio.response.Responseで@content_security_policy.setterが設定されているため、Responseのプロパティで登録できます。

response.content_security_policy = "default-src 'self'"
4

参考文献

1. A Minimal Application

# A Minimal Application | Quickstart — Flask Documentation (2.1.x)

2. Security Considerations

Security Considerations — Flask Documentation (2.1.x)

# Security Headers | Security Considerations — Flask Documentation (2.1.x)

▲