0
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?

【Python】Flaskでミニマムな認証機構を作成する

Last updated at Posted at 2025-04-05

はじめに

※この記事は、私が運営している技術ブログ(hirahira.blog)で公開していた内容を移植・加筆したものです。

PythonとFlaskで、ミニマムな認証機能を実装する方法を紹介します。

ライブラリ等を使わずにログイン機構を作成することは基本的に無いと思いますが、仕組みを理解するための学習用途であればおすすめです。

環境

  • Windows 11
  • Python 3.13.2
  • Flask 3.1.0

フォルダ構成

├ app.py
└ templates/
 ├ login.html
 ├ welcome.html
 └ contents.html

コード内容の解説

app.py

メインとなる認証機構を実装しています。

あくまで学習用途なので、セッションキー・ユーザー名・パスワードはソースコードにベタ書きです。

app.py
from flask import Flask, request, redirect, render_template, flash, session

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret_key'  # セッションの暗号化に使用するキー
app.config['USERNAME'] = 'user'  # ログイン用のユーザ名
app.config['PASSWORD'] = 'pass'  # ログイン用のパスワード

@app.route('/')
def index():
    # ログイン済みの場合はウェルカムページを表示、それ以外はログインページへリダイレクト
    if session.get('flag'):
        return render_template('welcome.html', username=session['username'])
    return redirect('/login')

@app.route('/login', methods=['GET'])
def login():
    # ログイン済みの場合はウェルカムページへリダイレクト
    if session.get('flag'):
        return redirect('/welcome')
    return render_template('login.html')  # ログインページを表示

@app.route('/login', methods=['POST'])
def login_post():
    # フォームから送信されたユーザ名とパスワードを取得
    username = request.form['username']
    password = request.form['password']
    # ユーザ名またはパスワードが一致しない場合はエラーメッセージを表示
    if username != app.config['USERNAME']:
        flash('ユーザ名が異なります')
    elif password != app.config['PASSWORD']:
        flash('パスワードが異なります')
    else:
        # 認証成功時にセッション情報を設定し、ウェルカムページへリダイレクト
        session['flag'] = True
        session['username'] = username
        return redirect('/welcome')
    return redirect('/login')  # 認証失敗時はログインページへリダイレクト

@app.route('/welcome')
def welcome():
    # ログイン済みの場合はウェルカムページを表示、それ以外はログインページへリダイレクト
    if session.get('flag'):
        return render_template('welcome.html', username=session['username'])
    return redirect('/login')

@app.route('/contents')
def contents():
    # ログイン済みの場合はコンテンツページを表示、それ以外はログインページへリダイレクト
    if session.get('flag'):
        return render_template('contents.html', username=session['username'])
    return redirect('/login')

@app.route('/logout')
def logout():
    # セッション情報を削除し、ログインページへリダイレクト
    session.pop('username', None)
    session.pop('flag', None)
    flash('ログアウトしました')
    return redirect('/login')

if __name__ == '__main__':
    # デバッグモードでアプリケーションを実行
    app.run(debug=True)

login.html

ログイン画面です。ユーザー名やパスワードが異なる場合はメッセージが表示されます。

login.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>ログイン</title>
  </head>
  <body>
    {% with messages = get_flashed_messages() %}
      {% if messages %}
        {% for message in messages %}
          <p>{{ message }}</p>
        {% endfor %}
      {% endif %}
    {% endwith %}
      <h1>ようこそ!</h1>
      <form action="/login" method="post">
      <div>
        <label for="user">ユーザー名</label>
        <input type="text" id="user" name="username">
      </div>
      <div>
        <label for="pass">パスワード</label>
        <input type="password" id="pass" name="password">
      </div>
      <button type="submit">ログイン</button>
    </form>
  </body>
</html>

welcome.html

ログイン後に表示されるページです。
ログインしたときのユーザーIDをrender_templateで渡しています。

ログアウトをクリックするとログイン画面に戻ります。

welcome.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Welcome</title>
</head>
<body>
  <h1>Welcomeページ</h1>
  <h2>ようこそ! {{ username }}さん</h2>
  <p>このページはログインしないと表示されません</p>
  <ul>
    <li><a href="{{ url_for('contents') }}">コンテンツ</a></li>
    <li><a href="{{ url_for('logout') }}">ログアウト</a></li>
  </ul>
</body>
</html>

contents.html

ログイン後に表示されるページから遷移できるページです。

contents.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>コンテンツ</title>
</head>
<body>
  <h1>コンテンツページ</h1>
  <h2>こんにちは! {{ username }}さん</h2>
  <p>このページはログインしないと表示されません</p>
  <ul>
    <li><a href="{{ url_for('welcome') }}">Welcomeページへ</a></li>
    <li><a href="{{ url_for('logout') }}">ログアウト</a></li>
  </ul>
</body>
</html>

動かしてみる

python app.py を実行し、http://127.0.0.1:5000 にアクセスするとログイン画面が表示されます。
image.png

設定したユーザー名とパスワードを入力するとWelcomeが表示されます。
image.png

セッションでフラグとユーザー名を変数で保持しており、ログアウトするかブラウザを閉じるまではログイン不要でページを閲覧できます。
image.png

ログアウトしました。
image.png

おわりに

Flaskを使って簡単な認証機構を作成しました。

本格的なアプリを作る際は、認証ライブラリの導入を検討しましょう。

0
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
0
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?