1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

クロスドメインになるバックエンドAPIサーバのFlask実装例

Posted at

実現したいこと

下記Flask部分の実装例を示す
image.png

環境

  • python 3.9.6
  • flask==2.0.1
  • flask-cors==3.0.10
  • flask-login==0.5.0

実装例

API要件

  • ログインしたらペットが参照できる
  • ログインしていなければペットが参照できない
app.py
#!/usr/bin/env python3
from datetime import timedelta
from flask import Flask, jsonify, request
import flask_cors
import flask_login

app = Flask(__name__)
login_manager = flask_login.LoginManager()
login_manager.init_app(app)
origins = ["https://AAA.com"]
flask_cors.CORS(
    app,
    # Cookieとクレデンシャルをドメイン間で送信できる
    supports_credentials=True,
    # フロントエンドのドメインを指定
    origins=origins,
)

app.config.update(
    SECRET_KEY="key",
    # セッションの有効期限1日
    PERMANENT_SESSION_LIFETIME=timedelta(days=1),
    # @flask_login.login_requiredのhttp通信を拒否する
    SESSION_COOKIE_SECURE=True,
    # JavaScriptがCookieへアクセスできなくする
    SESSION_COOKIE_HTTPONLY=True,
    # クロスドメインのバックエンド⇨クライアントでSet-Cookieを返す
    # Secure属性を付けないとNoneにできない
    SESSION_COOKIE_SAMESITE="None",
)


class User(flask_login.UserMixin):
    def __init__(self, user_id):
        self.id = user_id


@login_manager.user_loader
def user_loader(user_id):
    return User(user_id)


@app.route("/login", methods=["POST"])
def login():
    # formからのCSRF対策でoriginヘッダーをチェックする
    if request.headers.get("origin") not in origins:
        return jsonify({"message": "Unauthorized"}), 401

    # 簡易的なログイン処理
    if request.json["user_id"] == "qiita" and request.json["password"] == "1234":
        flask_login.login_user(User(request.json["user_id"]))
        return jsonify({"message": "Logined"})
    else:
        # 前のセッションが残らないようにログアウトする
        flask_login.logout_user()
        return jsonify({"message": "Bad Login"}), 401


@app.route("/pets", methods=["GET"])
# sessionが有効なときにアクセスできる処理
@flask_login.login_required
def pets():
    if request.headers.get("origin") not in origins:
        return jsonify({"message": "Unauthorized"}), 401

    return jsonify({"pets": [{"name": "dog"}]})


@app.route("/logout", methods=["POST"])
@flask_login.login_required
def logout():
    if request.headers.get("origin") not in origins:
        return jsonify({"message": "Unauthorized"}), 401

    flask_login.logout_user()
    return jsonify({"message": "Logouted"})


# sessionが有効でないときの処理
@login_manager.unauthorized_handler
def unauthorized_handler():
    return jsonify({"message": "Unauthorized"}), 401

参考

フロントエンド側ではクロスドメインでCookieを送信できるようにするため、
HTTPリクエストに"Access-Control-Allow-Credentials: true"ヘッダーを付与する

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?