Flaskでヘッダー情報をafter_requestで設定する
after_request
が便利だと気がついてしまいました。
初期状態でのヘッダー確認
公式に紹介されている最小限のアプリケーションは以下のようになります。
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の公式サイトにもあるようにセキュリティに関していくつか設定が必要になるケースがあります。
なので、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
の形での登録をよく見る気がします。
例えば、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'"
参考文献