如何使用 Flask-Login

2015-02-23

Flask-Login 可以做什麼?

Flask-Login provides user session management for Flask. It handles the common tasks of logging in, logging out, and remembering your users’ sessions over extended periods of time.

簡而言之就是替網站管理 session,這裡只說明最一般的用法,其功能當然不僅於此,如有需要可以參考 官方的說明文件

1. 安裝 / Installation

:::bash
$ pip install Flask-Login

2. 設定 / Configuration

首先必須將整個 app 套用 LoginManager

:::python
# app.py
from flask import Flask
from flask.ext.login import LoginManager

app = Flask(__name__)
login_manager = LoginManager()
login_manager.init_app(app)

#...

接下來是使用者(User)的model部分,有兩種方式,第一種是自行新增 function:

:::python
# models.py
from app import db

class User(db.Model):
    __tablename__ = 'user'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(100))
    password = db.Column(db.String(100))
    email = db.Column(db.String(100))

    def __init__(self, username=None, password=None, email=None):
        self.username = username
        self.password = password
        self.email = email

    def __repr__(self):
        return '<User %r>' % self.username

    # 新增下面四個 function
    def is_authenticated(self):
        return True

    def is_active(self):
        return True

    def is_anonymous(self):
        return False

    def get_id(self):
        return unicode(self.id)

或是直接繼承 UserMixin

:::python
# models.py
from flask.ext.login import UserMixin

class User(UserMixin):
    __tablename__ = 'user'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(100))
    password = db.Column(db.String(100))
    email = db.Column(db.String(100))

    def __init__(self, username=None, password=None, email=None):
        self.username = username
        self.password = password
        self.email = email

3. 使用 / Usage

使用的部分當然是在 views.py 上著墨了,首先要定義 load_user,確保網站的 current_user,記住傳入的 id 型態必須是 unicode

:::python
# views.py
from flask import render_template
from app import app, db, login_manager, bcrypt
from flask.ext.login import current_user, login_required, login_user, logout_user

#...

@login_manager.user_loader
def load_user(id):
    user = User.query.filter_by(id=id).first()
    return user

#...

再來是 login,其實大部份與一般 login 差不多,只是額外使用 login_user

:::python
# views.py
from flask import render_template, redirect
from app import app, db, login_manager, bcrypt
from models import User
from flask.ext.login import current_user, login_required, login_user, logout_user

#...

@login_manager.user_loader
def load_user(id):
    user = User.query.filter_by(id=id).first()
    return user

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        user = User.query.filter_by(username=request.form['username']).first()
        if user and bcrypt.check_password_hash(user.password, request.form['password']):
            # 儲存 session
            login_user(user)
            return redirect(url_for('index'))
    return render_template('login.html')

#...

網站一定都會有需要登入才能訪問的頁面,對此只需要在該個 view function 上加一個 decorator 即可:

:::python
# views.py

#...

@app.route("/dashboard")
@login_required
def dashboard():
    return render_template('dashboard.html')

#...

4. 其他較常使用

Logout

:::python
@app.route("/logout")
@login_required
def logout():
    logout_user()
    return redirect(url_for('login'))

Unauthorized Handler

:::python
@login_manager.unauthorized_handler
def unauthorized():
    # do stuff
    return redirect(url_for('login'))