FlaskでBasic認証
タイトル通りな感じで試したのでメモっておく。というかFlaskのドキュメントに載ってた。Flaskアプリ側でBasic認証を掛けたいという欲求
HTTP Basic Auth | Flask (A Python Microframework)
1. 準備
適当に2ページ分の出力をするFlaskアプリがあるとする。
- 「http://127.0.0.1/」 => Hello index!と出力
- 「http://127.0.0.1/hello」 => Hello World!と出力
from flask import Flask app = Flask(__name__) @app.route("/") @requires_auth def index(): return "Hello Index!" @app.route("/hello") def hello(): return "Hello World!" if __name__ == "__main__": app.run()
これを main.py とかいうファイル名だとする。
2. Basic認証用のデコレータを用意する
HTTP Basic Auth | Flask (A Python Microframework)
from functools import wraps from flask import request, Response def check_auth(username, password): """This function is called to check if a username / password combination is valid. """ return username == 'admin' and password == 'secret' def authenticate(): """Sends a 401 response that enables basic auth""" return Response( 'Could not verify your access level for that URL.\n' 'You have to login with proper credentials', 401, {'WWW-Authenticate': 'Basic realm="Login Required"'}) def requires_auth(f): @wraps(f) def decorated(*args, **kwargs): auth = request.authorization if not auth or not check_auth(auth.username, auth.password): return authenticate() return f(*args, **kwargs) return decorated
ここのコードをもってきて、「decorator.py」とかいうファイル名にする。
ここまででこんなファイル構成構成になってる
/decorator.py /main.py
3. デコレータ使ってみる
作ったデコレータを使ってみる。
from flask import Flask from decorator import requires_auth # <- 追加 app = Flask(__name__) @app.route("/") @requires_auth # <- 追加 def index(): return "Hello Index!" @app.route("/hello") def hello(): return "Hello World!" if __name__ == "__main__": app.run()
これで 「http://127.0.0.1/」にアクセスすると、ID/PASSが求められるので、「admin/secret」て入力すると認証が通る。
4. サイト全体でBasic認証をかける
上のまんまだと、「http://127.0.0.1/hello」にはデコレータが無いのでBasic認証かからない。hello のviewにもデコレータを設定すればよいが、viewがいっぱいあると、面倒、
Flaskは、全てのviewアクションに対して、前処理を入れられるフックポイントが用意してあるのでそれを利用してサイト全体にBasic認証をかける。
from flask import Flask from decorator import requires_auth app = Flask(__name__) @app.before_request # <- 全てのviewで前処理を行うためのdecoratorを使った関数を用意 @requires_auth #<- ここでBasic認証のdecoratorを使う def before_request(): pass @app.route("/") # <- 個別のviewからはデコレータを外した。 def index(): return "Hello Index!" @app.route("/hello") def hello(): return "Hello World!" if __name__ == "__main__": app.run()
これで サイト全体でBasic認証がかかるようになりました。Flaskが動く環境が有れば、Google App Engineとかでも大丈夫。