Flaskでアプリに認証を追加する方法-ログイン

提供:Dev Guides
移動先:案内検索

序章

ユーザーがアプリにログインできるようにすることは、Webアプリケーションに追加する最も一般的な機能の1つです。 Flask-Login パッケージを使用して、Flaskアプリに認証を追加できます。

このチュートリアルでは、次のことを行います。

  • セッション管理にFlask-Loginライブラリを使用する
  • パスワードのハッシュには、組み込みのFlaskユーティリティを使用します
  • ログインしたユーザーのみの保護されたページをアプリに追加します
  • Flask-SQLAlchemyを使用してUserモデルを作成します
  • ユーザーがアカウントを作成してログインするためのサインアップおよびログインフォームを作成します
  • 何か問題が発生したときにエラーメッセージをフラッシュしてユーザーに返す
  • ユーザーのアカウントからの情報を使用して、プロファイルページに表示します

サインアップとログインページを作成して、ユーザーがログインして保護されたページにアクセスできるようにします。 Userモデルの情報を使用し、ユーザーがログインしたときに保護されたページに表示して、プロファイルがどのようになるかをシミュレートします。

注:このチュートリアルは範囲が限定されており、セッションの高度な永続化については説明していません。 さらに、主キーのデータ型を変更したり、別のデータベースシステムに移行する際の考慮事項も、この入門チュートリアルの範囲外です。


このプロジェクトのソースコードはGitHubで入手できます。

前提条件

このチュートリアルを完了するには、次のものが必要です。

チュートリアルを完了すると、プロジェクトのファイル構造がどのようになるかを示す図を次に示します。

.
└── flask_auth_app
    └── project
        ├── __init__.py       # setup the app
        ├── auth.py           # the auth routes for the app
        ├── db.sqlite         # the database
        ├── main.py           # the non-auth routes for the app
        ├── models.py         # the user model
        └── templates
            ├── base.html     # contains common layout and links
            ├── index.html    # show the home page
            ├── login.html    # show the login form
            ├── profile.html  # show the profile page
            └── signup.html   # show the signup form

チュートリアルを進めるにつれて、これらのディレクトリとファイルを作成します。

このチュートリアルは、sqlite3 v3.36.0、python v3.9.8、flask v2.0.2、flask-login v0.5.0、および[ X113X]v2.5.1。

ステップ1—パッケージのインストール

プロジェクトに必要な3つの主要なパッケージがあります。

  • フラスコ
  • Flask-ログイン:認証後にユーザーセッションを処理します
  • Flask-SQLAlchemy:ユーザーモデルとデータベースとのインターフェースを表す

データベースに余分な依存関係をインストールする必要がないように、SQLiteを使用します。

まず、プロジェクトディレクトリの作成から始めます。

mkdir flask_auth_app

次に、プロジェクトディレクトリに移動します。

cd flask_auth_app

Python環境がない場合は、Python環境を作成することをお勧めします。

注: venvの設定については、ローカル環境に関連するチュートリアルを参照してください。


Pythonがマシンにどのようにインストールされたかに応じて、コマンドは次のようになります。

python3 -m venv auth

-mフラグはmodule-name用です。 このコマンドは、モジュールvenvを実行して、authという名前の新しい仮想環境を作成します。 これにより、bininclude、およびlibサブディレクトリを含む新しいディレクトリが作成されます。 そしてpyvenv.cfgファイル。

次に、次のコマンドを実行します。

source auth/bin/activate

このコマンドは、仮想環境をアクティブにします。

仮想環境から次のコマンドを実行して、必要なパッケージをインストールします。

pip install flask flask-sqlalchemy flask-login

パッケージをインストールしたので、メインのアプリファイルを作成する準備が整いました。

ステップ2—メインアプリファイルを作成する

projectディレクトリを作成することから始めましょう。

mkdir project

最初のファイルは、プロジェクトの__init__.pyファイルになります。

nano project/__init__.py

このアプリは、青写真付きのFlaskアプリファクトリパターンを使用します。 1つのブループリントは、インデックスと保護されたプロファイルページを含む通常のルートを処理します。 別の青写真は、認証関連のすべてを処理します。 実際のアプリでは、機能を好きなように分解できますが、ここで説明するソリューションは、このチュートリアルでうまく機能します。

このファイルには、データベースを初期化してブループリントを登録するアプリを作成する機能があります。 現時点では、これはあまり効果がありませんが、アプリの残りの部分で必要になります。

SQLAlchemyを初期化し、いくつかの構成値を設定し、ブループリントをここに登録する必要があります。

プロジェクト/__init__.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

# init SQLAlchemy so we can use it later in our models
db = SQLAlchemy()

def create_app():
    app = Flask(__name__)

    app.config['SECRET_KEY'] = 'secret-key-goes-here'
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'

    db.init_app(app)

    # blueprint for auth routes in our app
    from .auth import auth as auth_blueprint
    app.register_blueprint(auth_blueprint)

    # blueprint for non-auth parts of app
    from .main import main as main_blueprint
    app.register_blueprint(main_blueprint)

    return app

メインのアプリファイルができたので、ルートの追加を開始します。

ステップ3—ルートを追加する

ルートには、2つの設計図を使用します。

main_blueprintの場合、ホームページ(/)とプロファイルページ(/profile)があります。

まず、main.pyを作成します。

nano project/main.py

次に、main_blueprintを追加します。

project / main.py

from flask import Blueprint
from . import db

main = Blueprint('main', __name__)

@main.route('/')
def index():
    return 'Index'

@main.route('/profile')
def profile():
    return 'Profile'

auth_blueprintの場合、ログインページ(/login)とサインアップページ(/signup)の両方を取得するためのルートがあります。 最後に、アクティブユーザーをログアウトするためのログアウトルート(/logout)があります。

次に、auth.pyを作成します。

nano project/auth.py

次に、auth_blueprintを追加します。

project / auth.py

from flask import Blueprint
from . import db

auth = Blueprint('auth', __name__)

@auth.route('/login')
def login():
    return 'Login'

@auth.route('/signup')
def signup():
    return 'Signup'

@auth.route('/logout')
def logout():
    return 'Logout'

当面は、loginsignup、およびlogoutをテキストリターンで定義してください。 loginおよびsignupからのPOSTリクエストを処理するためのルートもあります。 後でこのコードに再度アクセスして、必要な機能で更新します。

ターミナルでは、FLASK_APPおよびFLASK_DEBUGの値を設定できます。

export FLASK_APP=project
export FLASK_DEBUG=1

FLASK_APP環境変数は、Flaskにアプリのロード方法を指示します。 これは、create_appが配置されている場所を指している必要があります。 このチュートリアルでは、projectディレクトリをポイントします。

FLASK_DEBUG環境変数は、1に設定することで有効になります。 これにより、ブラウザにアプリケーションエラーを表示するデバッガが有効になります。

flask_auth_appディレクトリにいることを確認してから、プロジェクトを実行します。

flask run

これで、Webブラウザーで、5つの可能なURLに移動して、auth.pyおよびmain.pyで定義された返されるテキストを確認できます。

たとえば、localhost:5000/profileにアクセスすると、次のように表示されます。Profile

ルートが期待どおりに動作していることを確認したら、テンプレートを作成できます。

ステップ4—テンプレートの作成

次に、アプリで使用するテンプレートを作成します。 これは、実際のログイン機能を実装する前の最初のステップです。

アプリは4つのテンプレートを使用します。

  • index.html
  • profile.html
  • login.html
  • signup.html

また、各ページに共通のコードを持つ基本テンプレートもあります。 この場合、基本テンプレートにはナビゲーションリンクとページの一般的なレイアウトが含まれます。

まず、projectディレクトリの下にtemplatesディレクトリを作成します。

mkdir -p project/templates

次に、base.htmlを作成します。

nano project/templates/base.html

次に、base.htmlファイルに次のコードを追加します。

project/templates/base.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Flask Auth Example</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" />
</head>

<body>
    <section class="hero is-primary is-fullheight">

        <div class="hero-head">
            <nav class="navbar">
                <div class="container">
                    <div id="navbarMenuHeroA" class="navbar-menu">
                        <div class="navbar-end">
                            <a href="{{ url_for('main.index') }}" class="navbar-item">
                                Home
                            </a>
                            <a href="{{ url_for('main.profile') }}" class="navbar-item">
                                Profile
                            </a>
                            <a href="{{ url_for('auth.login') }}" class="navbar-item">
                                Login
                            </a>
                            <a href="{{ url_for('auth.signup') }}" class="navbar-item">
                                Sign Up
                            </a>
                            <a href="{{ url_for('auth.logout') }}" class="navbar-item">
                                Logout
                            </a>
                        </div>
                    </div>
                </div>
            </nav>
        </div>

        <div class="hero-body">
            <div class="container has-text-centered">
               {% block content %}
               {% endblock %}
            </div>
        </div>
    </section>
</body>

</html>

このコードは、アプリケーションの各ページへの一連のメニューリンクを作成します。 また、子テンプレートで上書きできるcontentのブロックを確立します。

注:このチュートリアルでは、ブルマを使用してスタイリングとレイアウトを処理します。 Bulmaの詳細については、公式のBulmaドキュメントを読むことを検討してください。


次に、templates/index.htmlを作成します。

nano project/templates/index.html

新しく作成したファイルに次のコードを追加して、ページにコンテンツを追加します。

project/templates/index.html

{% extends "base.html" %}

{% block content %}
<h1 class="title">
  Flask Login Example
</h1>
<h2 class="subtitle">
  Easy authentication and authorization in Flask.
</h2>
{% endblock %}

このコードは、タイトルとサブタイトルを持つ基本的なインデックスページを作成します。

次に、templates/login.htmlを作成します。

nano project/templates/login.html

このコードは、EmailおよびPasswordのフィールドを持つログインページを生成します。 ログインしたセッションを「記憶」するためのチェックボックスもあります。

project/templates/login.html

{% extends "base.html" %}

{% block content %}
<div class="column is-4 is-offset-4">
    <h3 class="title">Login</h3>
    <div class="box">
        <form method="POST" action="/login">
            <div class="field">
                <div class="control">
                    <input class="input is-large" type="email" name="email" placeholder="Your Email" autofocus="">
                </div>
            </div>

            <div class="field">
                <div class="control">
                    <input class="input is-large" type="password" name="password" placeholder="Your Password">
                </div>
            </div>
            <div class="field">
                <label class="checkbox">
                    <input type="checkbox" name="remember">
                    Remember me
                </label>
            </div>
            <button class="button is-block is-info is-large is-fullwidth">Login</button>
        </form>
    </div>
</div>
{% endblock %}

次に、templates/signup.htmlを作成します。

nano project/templates/signup.html

次のコードを追加して、emailname、およびpasswordのフィールドを持つサインアップページを作成します。

project/templates/signup.html

{% extends "base.html" %}

{% block content %}
<div class="column is-4 is-offset-4">
    <h3 class="title">Sign Up</h3>
    <div class="box">
        <form method="POST" action="/signup">
            <div class="field">
                <div class="control">
                    <input class="input is-large" type="email" name="email" placeholder="Email" autofocus="">
                </div>
            </div>

            <div class="field">
                <div class="control">
                    <input class="input is-large" type="text" name="name" placeholder="Name" autofocus="">
                </div>
            </div>

            <div class="field">
                <div class="control">
                    <input class="input is-large" type="password" name="password" placeholder="Password">
                </div>
            </div>

            <button class="button is-block is-info is-large is-fullwidth">Sign Up</button>
        </form>
    </div>
</div>
{% endblock %}

次に、templates/profile.htmlを作成します。

nano project/templates/profile.html

このコードを追加して、Anthonyを歓迎するようにハードコードされたタイトルのページを作成します。

project/templates/profile.html

{% extends "base.html" %}

{% block content %}
<h1 class="title">
  Welcome, Anthony!
</h1>
{% endblock %}

後でこのコードに再度アクセスして、ユーザーに動的に挨拶します。

テンプレートを追加したら、各ルートのreturnステートメントを更新して、テキストの代わりにテンプレートを返すことができます。

次に、indexprofileのインポート行とルートを変更して、main.pyを更新します。

project / main.py

from flask import Blueprint, render_template
...
@main.route('/')
def index():
    return render_template('index.html')

@main.route('/profile')
def profile():
    return render_template('profile.html')

次に、loginsignupのインポート行とルートを変更して、auth.pyを更新します。

project / auth.py

from flask import Blueprint, render_template
...
@auth.route('/login')
def login():
    return render_template('login.html')

@auth.route('/signup')
def signup():
    return render_template('signup.html')

これらの変更を行った後、/signupに移動した場合のサインアップページは次のようになります。

//login/profileのページに移動することもできます。

後でテンプレートが表示されないため、/logoutは今のところそのままにしておきます。

ステップ5—ユーザーモデルの作成

ユーザーモデルは、アプリがユーザーを持つことの意味を表します。 このチュートリアルでは、emailアドレス、password、およびnameのフィールドが必要です。 将来のアプリケーションでは、ユーザーごとにはるかに多くの情報を保存することを決定する可能性があります。 誕生日、プロフィール写真、場所、または任意のユーザー設定などを追加できます。

Flask-SQLAlchemyで作成されたモデルは、データベース内のテーブルに変換されるクラスによって表されます。 これらのクラスの属性は、これらのテーブルの列に変わります。

Userモデルを作成します。

nano project/models.py

Userモデルを定義します。

project / models.py

from . import db

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy
    email = db.Column(db.String(100), unique=True)
    password = db.Column(db.String(100))
    name = db.Column(db.String(1000))

このコードは、idemailpassword、およびnameの列を持つUserを定義します。

Userモデルを作成したので、データベースの構成に進むことができます。

ステップ6—データベースの構成

SQLiteデータベースを使用します。 自分でSQLiteデータベースを作成することもできますが、Flask-SQLAlchemyに作成してもらいましょう。 __init__.pyファイルで指定されたデータベースのパスがすでにあるため、 PythonREPLでデータベースを作成するようにFlask-SQLAlchemyに指示する必要があります。

まだ仮想環境とflask_auth_appディレクトリにいることを確認してください。

アプリを停止してPythonREPLを開くと、dbオブジェクトでcreate_allメソッドを使用してデータベースを作成できます。

from project import db, create_app, models
db.create_all(app=create_app()) # pass the create_app result so Flask-SQLAlchemy gets the configuration.

注: Pythonインタープリターを初めて使用する場合は、公式ドキュメントを参照してください。


これで、プロジェクトディレクトリにdb.sqliteファイルが表示されます。 このデータベースには、ユーザーテーブルが含まれます。

ステップ7—認証機能の設定

サインアップ機能では、ユーザーがフォームに送信したデータを取得してデータベースに追加します。 同じ電子メールアドレスを持つユーザーがデータベースにまだ存在していないことを確認する必要があります。 存在しない場合は、データベースに配置する前に、パスワードをハッシュ化する必要があります。

注:パスワードをプレーンテキストで保存することは、セキュリティ対策としては不十分と見なされます。 通常、パスワードを安全に保つために、複雑なハッシュアルゴリズムとソルトが必要になります。


POSTフォームデータを処理するための2番目の関数を追加することから始めましょう。 ユーザーから渡されたデータを収集します。

インポート行を変更してsignup_postを実装することにより、auth.pyを更新します。

project / auth.py

from flask import Blueprint, render_template, redirect, url_for
...
@auth.route('/signup')
def signup():
    return render_template('signup.html')

@auth.route('/signup', methods=['POST'])
def signup_post():
    # code to validate and add user to database goes here
    return redirect(url_for('auth.login'))

関数を作成し、リダイレクトを追加します。 これにより、サインアップが成功し、ログインページに移動するユーザーエクスペリエンスが提供されます。

次に、ユーザーのサインアップに必要な残りのコードを追加しましょう。 リクエストオブジェクトを使用してフォームデータを取得します。

インポートを追加してsignup_postを実装することにより、auth.pyの更新を続行します。

auth.py

from flask import Blueprint, render_template, redirect, url_for, request
from werkzeug.security import generate_password_hash, check_password_hash
from .models import User
from . import db
...
@auth.route('/signup', methods=['POST'])
def signup_post():
    # code to validate and add user to database goes here
    email = request.form.get('email')
    name = request.form.get('name')
    password = request.form.get('password')

    user = User.query.filter_by(email=email).first() # if this returns a user, then the email already exists in database

    if user: # if a user is found, we want to redirect back to signup page so user can try again
        return redirect(url_for('auth.signup'))

    # create a new user with the form data. Hash the password so the plaintext version isn't saved.
    new_user = User(email=email, name=name, password=generate_password_hash(password, method='sha256'))

    # add the new user to the database
    db.session.add(new_user)
    db.session.commit()

    return redirect(url_for('auth.login'))

このコードは、同じ電子メールアドレスを持つユーザーがデータベースに存在するかどうかを確認します。

ステップ8—サインアップ方法のテスト

サインアップ方法が完了したので、新しいユーザーを作成できるようになります。 フォームをテストしてユーザーを作成しましょう。

サインアップが成功したかどうかを確認する方法は2つあります。

  • データベースビューアを使用して、テーブルに追加された行を確認できます。
  • または、同じメールアドレスで再度登録してみてください。エラーが発生した場合は、最初のメールが正しく保存されていることがわかります。

メールがすでに存在することをユーザーに知らせ、ログインページに移動するようにユーザーに指示するコードを追加しましょう。 flash関数を呼び出すことにより、次のリクエスト(この場合はリダイレクト)にメッセージを送信できます。 ユーザーがリダイレクトされるページは、テンプレート内のそのメッセージにアクセスできるようになります。

サインアップページにリダイレクトする前に、まずflashを追加します。

project / auth.py

from flask import Blueprint, render_template, redirect, url_for, request, flash
...
@auth.route('/signup', methods=['POST'])
def signup_post():
    ...
    if user: # if a user is found, we want to redirect back to signup page so user can try again
        flash('Email address already exists')
        return redirect(url_for('auth.signup'))

テンプレートでフラッシュされたメッセージを取得するには、フォームの前にこのコードを追加します。

project/templates/signup.html

...
{% with messages = get_flashed_messages() %}
{% if messages %}
    <div class="notification is-danger">
        {{ messages[0] }}. Go to <a href="{{ url_for('auth.login') }}">login page</a>.
    </div>
{% endif %}
{% endwith %}
<form method="POST" action="/signup">

電子メールアドレスがすでにデータベースにある場合、このコードはメッセージ"Email address already exists. Go to login page."を表示します。

この時点で、アプリケーションを実行して、既存の電子メールアドレスでサインアップを試みることができます。

ステップ9—ログイン方法の追加

ログイン方法は、サインアップ機能に似ています。 この場合、入力されたemailアドレスを比較して、データベースにあるかどうかを確認します。 その場合、ユーザーが渡したpasswordをハッシュし、データベース内のハッシュされたpasswordと比較することにより、ユーザーが提供したpasswordをテストします。 両方のハッシュされたpasswordが一致すると、ユーザーが正しいpasswordを入力したことがわかります。

ユーザーがパスワードチェックに合格すると、ユーザーが正しい資格情報を持っていることがわかり、Flask-Loginを使用してログインできます。 login_userを呼び出すことにより、Flask-Loginはそのユーザーのセッションを作成し、ユーザーがログインしたままでいる間持続します。これにより、ユーザーは保護されたページを表示できます。

POSTで送信されたデータを処理するための新しいルートから始めることができます。 そして、ユーザーが正常にログインしたら、プロファイルページにリダイレクトします。

project / auth.py

...
@auth.route('/login')
def login():
    return render_template('login.html')

@auth.route('/login', methods=['POST'])
def login_post():
    # login code goes here
    return redirect(url_for('main.profile'))

次に、ユーザーが正しい資格情報を持っているかどうかを確認する必要があります。

project / auth.py

...
@auth.route('/login', methods=['POST'])
def login_post():
    # login code goes here
    email = request.form.get('email')
    password = request.form.get('password')
    remember = True if request.form.get('remember') else False

    user = User.query.filter_by(email=email).first()

    # check if the user actually exists
    # take the user-supplied password, hash it, and compare it to the hashed password in the database
    if not user or not check_password_hash(user.password, password):
        flash('Please check your login details and try again.')
        return redirect(url_for('auth.login')) # if the user doesn't exist or password is wrong, reload the page

    # if the above check passes, then we know the user has the right credentials
    return redirect(url_for('main.profile'))

テンプレートにブロックを追加して、ユーザーがフラッシュされたメッセージを確認できるようにします。

project/templates/login.html

...
{% with messages = get_flashed_messages() %}
{% if messages %}
    <div class="notification is-danger">
        {{ messages[0] }}
    </div>
{% endif %}
{% endwith %}
<form method="POST" action="/login">

これで、ユーザーが正常にログインしたと言うことができますが、ユーザーをログインさせるものは何もありません。

Flask-ログインはユーザーセッションを管理できます。 UserMixinをユーザーモデルに追加することから始めます。 UserMixinは、Flask-Login属性をモデルに追加して、Flask-Loginがモデルを操作できるようにします。

models.py

from flask_login import UserMixin
from . import db

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy
    email = db.Column(db.String(100), unique=True)
    password = db.Column(db.String(100))
    name = db.Column(db.String(1000))

次に、ユーザーローダーを指定する必要があります。 ユーザーローダーは、セッションCookieに保存されているIDから特定のユーザーを見つける方法をFlask-Loginに指示します。 これをcreate_app関数に、Flask-Loginのinitコードとともに追加します。

プロジェクト/__init__.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
...
def create_app():
    ...
    db.init_app(app)

    login_manager = LoginManager()
    login_manager.login_view = 'auth.login'
    login_manager.init_app(app)

    from .models import User

    @login_manager.user_loader
    def load_user(user_id):
        # since the user_id is just the primary key of our user table, use it in the query for the user
        return User.query.get(int(user_id))

最後に、プロファイルページにリダイレクトしてセッションを作成する前に、login_user関数を追加します。

project / auth.py

from flask_login import login_user
from .models import User
from . import db
...
@auth.route('/login', methods=['POST'])
def login_post():
    ...
    # if the above check passes, then we know the user has the right credentials
    login_user(user, remember=remember)
    return redirect(url_for('main.profile'))

Flask-Loginセットアップでは、/loginルートを使用します。 すべてが整ったら、プロフィールページが表示されます。

この時点で、アプリケーションを実行してログインを試みることができます。

ステップ10—ページを保護する

あなたの名前がAnthonyでない場合は、プロフィールページにあなたの名前が間違っていることがわかります。 目標は、プロファイルがデータベースに名前を表示することです。 nameを取得するには、ページを保護してからユーザーのデータにアクセスする必要があります。

Flask-Loginを使用するときにページを保護するには、ルートと関数の間に@login_requriedデコレータを追加します。 これにより、ログインしていないユーザーにはルートが表示されなくなります。 ユーザーがログインしていない場合、Flask-Login構成に従って、ユーザーはログインページにリダイレクトされます。

@login_requiredデコレータでデコレートされたルートでは、関数内でcurrent_userオブジェクトを使用できます。 このcurrent_userはデータベースからのユーザーを表し、ドット表記を使用してそのユーザーのすべての属性へのアクセスを提供します。 たとえば、current_user.emailcurrent_user.passwordcurrent_user.name、およびcurrent_user.idは、ログインしたユーザーのデータベースに保存されている実際の値を返します。

current_usernameを使用して、テンプレートに送信してみましょう。

project / main.py

from flask import Blueprint, render_template
from flask_login import login_required, current_user
from . import db
...
@main.route('/profile')
@login_required
def profile():
    return render_template('profile.html', name=current_user.name)

次に、profile.htmlファイルで、ページを更新してnameの値を表示します。

project/templates/profile.html

...
<h1 class="title">
  Welcome, {{ name }}!
</h1>

ユーザーがプロフィールページにアクセスすると、nameが表示されます。

ログアウトビューを更新するには、ログアウトルートでlogout_user関数を呼び出します。

project / auth.py

from flask_login import login_user, login_required, logout_user
...
@auth.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('main.index'))

そもそもログインしていないユーザーをログアウトしても意味がないので、@login_requiredデコレータを使用してください。

ユーザーがログアウトしてプロファイルページを再度表示しようとすると、次のエラーメッセージが表示されます。

これは、ユーザーがページへのアクセスを許可されていない場合に、Flask-Loginがメッセージをフラッシュするためです。

最後に行うことは、ifステートメントをテンプレートに入れて、ユーザーに関連するリンクのみを表示することです。

テンプレート/base.html

...
<div class="navbar-end">
    <a href="{{ url_for('main.index') }}" class="navbar-item">
        Home
    </a>
    {% if current_user.is_authenticated %}
    <a href="{{ url_for('main.profile') }}" class="navbar-item">
        Profile
    </a>
    {% endif %}
    {% if not current_user.is_authenticated %}
    <a href="{{ url_for('auth.login') }}" class="navbar-item">
        Login
    </a>
    <a href="{{ url_for('auth.signup') }}" class="navbar-item">
        Sign Up
    </a>
    {% endif %}
    {% if current_user.is_authenticated %}
    <a href="{{ url_for('auth.logout') }}" class="navbar-item">
        Logout
    </a>
    {% endif %}
</div>

ユーザーがログインする前に、ログインまたはサインアップするオプションがあります。 ログイン後、自分のプロファイルに移動するか、ログアウトすることができます。

これで、認証を使用してアプリを正常に構築できました。

結論

このチュートリアルでは、Flask-LoginとFlask-SQLAlchemyを使用して、アプリのログインシステムを構築しました。 最初にユーザーモデルを作成し、ユーザー情報を保存することで、ユーザーを認証する方法について説明しました。 次に、フォームからパスワードをハッシュし、データベースに保存されているパスワードと比較して、ユーザーのパスワードが正しいことを確認する必要がありました。 最後に、プロファイルページで@login_requiredデコレータを使用してアプリに認証を追加し、ログインしているユーザーのみがそのページを表示できるようにしました。

このチュートリアルで作成したものは小さなアプリには十分ですが、最初からより多くの機能が必要な場合は、Flask-UserライブラリまたはFlask-Securityライブラリのいずれかを使用することを検討してください。 Flask-ログインライブラリ。