Flask-Login でログイン機能を作ってみる

Posted on Mon 06 May 2019 in misc

Flask-Login を使ってログイン機能を作ってみました。 ログインするところだけです。ユーザー登録等は作っていません。

参考にしたページ が分かりやすかったです。 スクリプトファイルに直書きですが、ユーザーも作って認証させる処理は加えました。

#!/usr/bin/env python3
"""flask-login sampler."""

import flask
import flask_login


app = flask.Flask(__name__)
app.secret_key = b'boizagie'

login_manager = flask_login.LoginManager()
login_manager.init_app(app)


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

    def get_id(self):
        return self.user_id


users = [
    User(1, 'Ichiro', 'foobar'),
    User(2, 'Jiro', 'fizzbuzz')
]


@login_manager.user_loader
def load_user(user_id):
    return users[int(user_id) - 1]


@app.route('/', methods=['GET'])
def index():
    def on_get():

        if flask_login.current_user.is_authenticated:
            content = '<a href="logout">Log out</a>'
        else:
            content = '<a href="login">Log in</a>'

        return (
            '''<html>
                  <head>
                    <title>{title}</title>
                  </head>
                  <body>
                    <h1>{title}</h1>
                      <p>{content}</p>
                  </body>
                </html>
            ''').format(title=__doc__.splitlines()[0][:-1],
                        content=content)

    if flask.request.method == 'GET':
        return on_get()


@app.route('/login', methods=['GET', 'POST'])
def login():
    def on_get():
        if flask_login.current_user.is_authenticated:
            return flask.redirect(flask.url_for('user'))
        else:
            return (
                '''<html>
                      <head>
                        <title>{title}</title>
                      </head>
                      <body>
                        <h1>{title}</h1>
                        <form action+"login" method="post">
                          <label for="username">username</label>
                          <input type="text" name="username" id="username">
                          <label for="password">password</label>
                          <input type="text" name="password" id="password">
                          <input type="submit" value="Log in">
                        </form>
                      </body>
                    </html>
                ''').format(title='Log in')

    def on_post():
        user_exists = False
        is_password_valid = False
        for user in users:
            user_exists = flask.request.form['username'] == user.username
            user_id = user.user_id
            if user_exists:
                is_password_valid = (
                    flask.request.form['password'] == user.password
                )
                break
        if user_exists and is_password_valid:
            flask_login.login_user(users[int(user_id) - 1])
            flask.session.clear()
            flask.session['user_id'] = user_id
            return flask.redirect(flask.url_for('user'))
        else:
            return flask.redirect(flask.url_for('index'))

    if flask.request.method == 'GET':
        return on_get()
    elif flask.request.method == 'POST':
        return on_post()


@app.route('/logout', methods=['GET'])
def logout():
    def on_get():
        flask_login.logout_user()
        return flask.redirect(flask.url_for('index'))

    if flask.request.method == 'GET':
        return on_get()


@app.route('/user', methods=['GET'])
@flask_login.login_required
def user():
    return (
        '''<html>
              <head>
                <title>User</title>
              </head>
              <body>
                <h1>Welcome!! {username}</h1>
                  <p><a href="logout">Log out</a></p>
              </body>
            </html>
        ''').format(
            username=users[int(flask.session['user_id']) - 1].username
        )


if __name__ == '__main__':
app.run()

まあでも、参考ページがわかりやすいとか言っていないで、 公式ドキュメントを読めるようにならないと…。