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

2022-06-02

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

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

公式に紹介されている最小限のアプリケーション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'}

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

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

...

おまけ

よくある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'"

参考文献