こちらのサンプルを改造しました。
asic Usage
Ubuntu での必要なライブラリーのインストール
sudo apt install python3-python-flask-jwt-extended
JWT_SECRET_KEY は次のコマンドで作成しました。
openssl rand -hex 32
ユーザーは 3人にしました。
user | password |
---|---|
scott | tiger123 |
jack | jack123 |
betty | betty123 |
サーバープログラムの仕様
- http://localhost:5000/login POST で ユーザー名とパスワードを渡すと、JWT トークンが返される
- http://localhost:5000/protected GET で ヘッダーに 正しい JWT トークンがあれば、logged_in_as というメッセージが返される
サーバープログラム
app.py
from flask import Flask
from flask import jsonify
from flask import request
from flask_jwt_extended import create_access_token
from flask_jwt_extended import get_jwt_identity
from flask_jwt_extended import jwt_required
from flask_jwt_extended import JWTManager
app = Flask(__name__)
# Setup the Flask-JWT-Extended extension
app.config["JWT_SECRET_KEY"] = "04e630f86a2d29c1fbbe76f5e8ea80475720a93d9c497a408255b7f3873ca385"
jwt = JWTManager(app)
# Create a route to authenticate your users and return JWTs. The
# create_access_token() function is used to actually generate the JWT.
@app.route("/login", methods=["POST"])
def login():
users = {}
users['scott'] = 'tiger123'
users['jack'] = 'jack123'
users['betty'] = 'betty123'
username = request.json.get("username", None)
password = request.json.get("password", None)
# if username != "scott" or password != "tiger123":
if (not username in users) or (password != users[username]):
return jsonify({"msg": "Bad username or password"}), 401
access_token = create_access_token(identity=username)
return jsonify(access_token=access_token)
# Protect a route with jwt_required, which will kick out requests
# without a valid JWT present.
@app.route("/protected", methods=["GET"])
@jwt_required()
def protected():
# Access the identity of the current user with get_jwt_identity
current_user = get_jwt_identity()
return jsonify(logged_in_as=current_user), 200
if __name__ == "__main__":
app.run()
サーバーの実行
python app.py
$ python app.py
* Serving Flask app 'app'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
テストスクリプト
http GET :5000/protected
$ http GET :5000/protected
HTTP/1.1 401 UNAUTHORIZED
Connection: close
Content-Length: 39
Content-Type: application/json
Date: Sun, 21 May 2023 08:44:44 GMT
Server: Werkzeug/2.2.2 Python/3.11.2
{
"msg": "Missing Authorization Header"
}
ログイン (token の取得)
login.sh
http POST :5000/login username=scott password=tiger123 > scott.json
http POST :5000/login username=jack password=jack123 > jack.json
http POST :5000/login username=betty password=betty123 > betty.json
ページへのアクセス
get.sh
JWT=`jq .access_token scott.json | sed 's/"//g'`
http GET :5000/protected Authorization:"Bearer $JWT"
#
JWT=`jq .access_token jack.json | sed 's/"//g'`
http GET :5000/protected Authorization:"Bearer $JWT"
#
JWT=`jq .access_token betty.json | sed 's/"//g'`
http GET :5000/protected Authorization:"Bearer $JWT"
実行結果
$ ./get.sh
HTTP/1.1 200 OK
Connection: close
Content-Length: 25
Content-Type: application/json
Date: Sun, 21 May 2023 08:46:56 GMT
Server: Werkzeug/2.2.2 Python/3.11.2
{
"logged_in_as": "scott"
}
HTTP/1.1 200 OK
Connection: close
Content-Length: 24
Content-Type: application/json
Date: Sun, 21 May 2023 08:46:57 GMT
Server: Werkzeug/2.2.2 Python/3.11.2
{
"logged_in_as": "jack"
}
HTTP/1.1 200 OK
Connection: close
Content-Length: 25
Content-Type: application/json
Date: Sun, 21 May 2023 08:46:57 GMT
Server: Werkzeug/2.2.2 Python/3.11.2
{
"logged_in_as": "betty"
}
確認したバージョン
$ flask --version
Python 3.12.7
Flask 3.0.3
Werkzeug 3.0.3