首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

Flask 框架實作簡易登入系統完整教學

     編輯:更多程式設計知識

在 Web 開發中,使用者登入是核心基礎功能。本教學將引導你使用 Flask 搭配 Flask-Login 與 Flask-OpenID 擴展,從零打造一套完整的使用者認證系統,涵蓋註冊、登入、登出與「記住我」功能。

環境準備與擴展配置

首先在 app/__init__.py 初始化兩大擴展:

import os
from flaskext.login import LoginManager
from flaskext.openid import OpenID
from config import basedir

lm = LoginManager()
lm.setup_app(app)
lm.login_view = 'login'  # 指定登入視圖端點

oid = OpenID(app, os.path.join(basedir, 'tmp'))  # OpenID 需要暫存目錄

User 模型實作 Flask-Login 介面

在 app/models.py 中,User 類別必須實作四個必要方法:

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    nickname = db.Column(db.String(64), unique=True)
    email = db.Column(db.String(120), unique=True)
    role = db.Column(db.SmallInteger, default=ROLE_USER)
    posts = db.relationship('Post', backref='author', lazy='dynamic')

    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)  # 必須回傳 unicode

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

使用者載入回調

在 app/views.py 註冊 user_loader,將 unicode ID 轉為整數查詢:

@lm.user_loader
def load_user(id):
    return User.query.get(int(id))

登入視圖與 OpenID 流程

@app.route('/login', methods=['GET', 'POST'])
@oid.loginhandler
def login():
    if g.user is not None and g.user.is_authenticated():
        return redirect(url_for('index'))
    form = LoginForm()
    if form.validate_on_submit():
        session['remember_me'] = form.remember_me.data
        return oid.try_login(form.openid.data, ask_for=['nickname', 'email'])
    return render_template('login.html', title='Sign In', form=form,
                           providers=app.config['OPENID_PROVIDERS'])
  • oid.loginhandler 標記此為 OpenID 登入端點。
  • 若使用者已登入,直接導向首頁。
  • 表單驗證通過後,將 remember_me 存入 Flask session,再呼叫 oid.try_login 發起 OpenID 驗證。

OpenID 回調處理

@oid.after_login
def after_login(resp):
    if resp.email is None or resp.email == '':
        flash('Invalid login. Please try again.')
        return redirect(url_for('login'))
    user = User.query.filter_by(email=resp.email).first()
    if user is None:
        nickname = resp.nickname or resp.email.split('@')[0]
        nickname = User.make_unique_nickname(nickname)  # 確保唯一
        user = User(nickname=nickname, email=resp.email, role=ROLE_USER)
        db.session.add(user)
        db.session.commit()
    remember_me = session.pop('remember_me', False)
    login_user(user, remember=remember_me)
    return redirect(request.args.get('next') or url_for('index'))

此處處理新用戶自動註冊、昵稱衝突解決、登入狀態建立與「下一頁」導向。

全域 g.user 與請求前置處理

@app.before_request
def before_request():
    g.user = current_user

將 Flask-Login 的 current_user 複製到 g,方便視圖與模板存取。

首頁視圖加上登入保護

@app.route('/')
@app.route('/index')
@login_required
def index():
    user = g.user
    posts = g.user.followed_posts().all()  # 後續會改為分頁
    return render_template('index.html', title='Home', user=user, posts=posts)

登出功能與導覽列整合

@app.route('/logout')
def logout():
    logout_user()
    return redirect(url_for('index'))

在 base.html 導覽列加入登出連結:

{% if g.user.is_authenticated() %}
| <a href="{{ url_for('logout') }}">Logout</a>
{% endif %}

完成以上步驟,即擁有一套可用的 OpenID 登入系統。下一階段可進一步加入單元測試、分頁、全文搜尋等進階功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved