Flask用戶認證:Flask-Login實現登錄功能

在Web應用中,用戶認證是確保數據安全和個性化體驗的基礎。比如,只有登錄用戶才能訪問個人中心、提交訂單等功能。Flask-Login是一個輕量級的Flask擴展,專門用於管理用戶會話,簡化登錄、登出和權限控制的實現。本文將用最簡單的方式,帶你一步步實現基於Flask-Login的用戶登錄功能。

一、爲什麼需要Flask-Login?

在沒有Flask-Login時,我們需要手動處理用戶會話(比如用session存儲用戶ID)、驗證密碼、管理登錄狀態等。而Flask-Login幫我們封裝了這些邏輯,只需幾行代碼就能實現:
- 自動維護用戶會話(保存用戶ID)
- 提供@login_required裝飾器保護路由
- 處理用戶登錄、登出的核心邏輯

二、準備工作

首先安裝必要的庫:

pip install flask flask-login

Flask-Login的核心是LoginManager,它會管理用戶會話和登錄狀態。此外,我們需要一個“用戶模型”來存儲用戶信息(這裏用簡單的類模擬)。

三、實現步驟(附代碼)

1. 初始化應用和Flask-Login
from flask import Flask, render_template, redirect, url_for, request, flash
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user

# 初始化Flask應用
app = Flask(__name__)
app.secret_key = 'your-secret-key-here'  # 必須設置,用於加密會話數據

# 初始化Flask-Login的LoginManager
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'  # 未登錄時跳轉的路由(比如/login)
2. 創建用戶模型

Flask-Login要求用戶類繼承UserMixin,它會自動實現is_authenticatedis_active等屬性(無需手動寫這些方法)。我們用一個簡單的User類模擬用戶數據:

class User(UserMixin):
    def __init__(self, user_id, username, password):
        self.id = user_id  # 用戶ID(必須)
        self.username = username  # 用戶名
        self.password = password  # 密碼(實際項目中必須加密存儲!)

# 模擬用戶數據庫(實際項目用SQLite/MySQL等)
users_db = {
    1: User(id=1, username='admin', password='123456'),
    2: User(id=2, username='guest', password='654321')
}
3. 實現用戶加載函數(關鍵!)

Flask-Login需要知道如何從會話中加載用戶。通過user_loader回調函數,根據用戶ID從數據庫中找到對應的用戶:

@login_manager.user_loader
def load_user(user_id):
    """根據用戶ID加載用戶對象"""
    return users_db.get(int(user_id))  # 從模擬數據庫中查詢用戶
4. 實現登錄功能

創建登錄視圖函數,處理用戶輸入的用戶名和密碼,驗證成功後調用login_user(user)記錄會話:

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        # 獲取用戶輸入
        username = request.form.get('username')
        password = request.form.get('password')

        # 模擬用戶驗證(實際項目需查詢數據庫+加密比對)
        user = None
        for u in users_db.values():
            if u.username == username and u.password == password:
                user = u
                break

        if user:
            # 登錄成功:調用login_user記錄會話
            login_user(user)  # 會將用戶ID存入session
            return redirect(url_for('home'))  # 重定向到首頁
        else:
            flash('用戶名或密碼錯誤!')  # 顯示錯誤提示

    # GET請求時渲染登錄表單
    return render_template('login.html')
5. 實現登出功能

登出時調用logout_user清除會話:

@app.route('/logout')
@login_required  # 只有登錄用戶才能訪問登出路由
def logout():
    logout_user()  # 清除會話,用戶登出
    return redirect(url_for('home'))  # 重定向到首頁
6. 保護路由(驗證登錄狀態)

@login_required裝飾器標記需要登錄才能訪問的路由:

@app.route('/profile')
@login_required  # 未登錄用戶會被重定向到login_view
def profile():
    """個人中心:只有登錄用戶可見"""
    return f"歡迎回來,{current_user.username}!"
7. 首頁和模板

首頁顯示歡迎信息和登錄狀態:

@app.route('/')
def home():
    return render_template('home.html')

模板文件(templates/home.html):

<!DOCTYPE html>
<html>
<head>
    <title>Flask-Login示例</title>
</head>
<body>
    <h1>首頁</h1>
    {% if current_user.is_authenticated %}
        <p>當前用戶:{{ current_user.username }}</p>
        <a href="{{ url_for('profile') }}">進入個人中心</a>
        <br>
        <a href="{{ url_for('logout') }}">登出</a>
    {% else %}
        <p>您尚未登錄,請<a href="{{ url_for('login') }}">登錄</a></p>
    {% endif %}
</body>
</html>

登錄模板(templates/login.html):

<!DOCTYPE html>
<html>
<head>
    <title>登錄</title>
</head>
<body>
    <h1>登錄</h1>
    {% with messages = get_flashed_messages() %}
        {% if messages %}
            <p style="color: red;">{{ messages[0] }}</p>
        {% endif %}
    {% endwith %}
    <form method="POST">
        <input type="text" name="username" placeholder="用戶名" required><br><br>
        <input type="password" name="password" placeholder="密碼" required><br><br>
        <button type="submit">登錄</button>
    </form>
</body>
</html>

四、運行測試

  1. 保存上述代碼到app.py,並在同目錄下創建templates文件夾,放入home.htmllogin.html
  2. 運行應用:python app.py
  3. 訪問 http://127.0.0.1:5000,點擊“登錄”,輸入用戶名admin/guest和密碼123456/654321,即可進入個人中心。

五、注意事項

  1. 密碼安全:示例中密碼是明文存儲,實際項目必須用bcryptwerkzeug.security加密(例如generate_password_hashcheck_password_hash)。
  2. 會話安全:生產環境中app.secret_key需設置爲複雜隨機字符串,避免硬編碼。
  3. 擴展功能:可添加“記住我”功能(login_user(user, remember=True))、密碼重置、權限管理等,Flask-Login支持這些高級特性。

總結

Flask-Login通過簡潔的API,快速實現了用戶認證的核心功能:登錄、登出、會話管理和路由保護。本文用最簡單的示例帶你入門,後續可結合數據庫和前端框架(如Bootstrap)進一步完善。

(完整代碼見上述步驟,可複製到本地運行測試)

小夜