裝飾器 validate_tokens 完整使用手冊

2025/1/12 手冊自製網頁模板授權元件

# 目錄

  1. 簡介
  2. 使用說明
  3. 依賴項目
  4. 驗證邏輯解釋
  5. 裝飾器的詳細使用
  6. 錯誤處理
  7. 測試與運行
  8. 結論

# 1. 簡介

validate_tokens 是一個用於 Flask 的裝飾器,能夠幫助你驗證用戶的登入狀態與角色權限。它通過檢查 LINE 的 access_tokenid_token,來確認用戶是否已登入以及是否擁有訪問某些頁面的權限。裝飾器提供了靈活的配置,允許你指定角色來限制不同用戶的權限,並且處理 Token 過期或不一致的情況。


# 2. 使用說明

要使用 validate_tokens 裝飾器,你需要將它應用於 Flask 路由中,用來保護需要登入和/或擁有特定角色的頁面。這個裝飾器主要針對 API Token 驗證,因此使用的是基於 Cookie 的 access_tokenid_token

# 基本範例

from flask import Flask, render_template
from your_module import validate_tokens  # 從你定義的模組中導入 validate_tokens

app = Flask(__name__)

@app.route('/dashboard')
@validate_tokens()  # 任何已登入的用戶都可以訪問
def dashboard(user_profile):
    return render_template('dashboard.html', user_profile=user_profile)

@app.route('/admin')
@validate_tokens(required_role='admin')  # 僅限擁有 admin 權限的用戶訪問
def admin_panel(user_profile):
    return render_template('admin_panel.html', user_profile=user_profile)
  • @validate_tokens():對於只需要登入驗證的頁面,可以直接使用,不用傳入任何參數。
  • @validate_tokens(required_role='admin'):對於需要特定角色的頁面,如 admin,必須檢查用戶是否具備此角色。

# 3. 依賴項目

你需要確保安裝和導入以下的 Python 庫和模組才能正常運行此裝飾器。

# 必須導入的依賴:

  • Flask:網頁框架,用於處理 HTTP 請求與路由。

    • 安裝:pip install flask
  • requests:用來發送 HTTP 請求,檢查 access_tokenid_token 是否有效。

    • 安裝:pip install requests
  • utils 模組

    • ConfigManager:用於管理配置,從配置檔案中獲取 CLIENT_ID 等關鍵值。
    • validate_signed_token:用於驗證簽名 Token,確保 Token 的有效性。
    • revoke_tokens:在 Token 無效或過期時,撤銷用戶的 Token。
    • UserManagement:用於操作用戶數據庫,如檢查用戶的角色權限。

# 裝飾器中需要的模組:

from functools import wraps
from flask import request, jsonify, render_template, make_response
import requests
from utils.config_manager import ConfigManager
from utils.token_utils import validate_signed_token
from utils.line_login_api import revoke_tokens
from utils.sql import UserManagement  # 替換為實際的模組名

這些模組的主要功能如下:

  • request: 用於從請求中提取 Cookie。
  • jsonify: 將 Python 字典轉換為 JSON 格式。
  • render_template: 渲染 HTML 模板。
  • make_response: 創建自定義響應,允許設置或刪除 Cookie。
  • requests: 發送 HTTP 請求,用於與外部 API 互動。
  • ConfigManager: 配置管理,用來獲取 API 認證憑證。
  • validate_signed_token: 驗證 JWT Token,保證 Token 的有效性和一致性。
  • revoke_tokens: 撤銷失效的 Token。

# 4. 驗證邏輯解釋

validate_tokens 的工作流程如下:

  1. 檢查 Cookie

    • 首先,從用戶的 Cookie 中獲取 access_tokenid_tokensigned_token
    • 如果任意一個缺失,則跳轉到登出頁面並清除 Cookie。
  2. 驗證 Access Token

    • 使用 access_token 向 LINE 的 API 發送請求,檢查用戶是否已經登入。
    • 如果 Token 無效,則返回 "Invalid Access Token" 錯誤並清除 Token。
  3. 檢查簽名 Token 一致性

    • 使用 validate_signed_token 驗證 JWT Token 的有效性。
    • 驗證 Token 中的 access_tokenid_token 是否與 Cookie 中的值匹配。
    • 如果不一致,則撤銷 Token 並跳轉到 "Token Mismatch" 頁面。
  4. ID Token 驗證

    • 使用 id_token 向 LINE 的驗證服務請求,確認用戶身份是否有效。
    • 如果無效,返回 "Invalid ID Token" 錯誤。
  5. 角色權限檢查

    • 如果指定了 required_role,則根據用戶 ID 檢查用戶是否具備所需角色。
    • 如果用戶具備角色,則允許訪問;如果不具備角色,則返回 "403 禁止訪問" 錯誤。

# 5. 裝飾器的詳細使用

# a. 不需要特定角色,只要已登入的使用場景:

@app.route('/profile')
@validate_tokens()  # 只需驗證登入狀態,不要求特定角色
def profile_page(user_profile):
    return render_template('profile.html', user_profile=user_profile)

# b. 限定特定角色的使用場景:

@app.route('/admin')
@validate_tokens(required_role='admin')  # 需要 "admin" 權限才能訪問
def admin_panel(user_profile):
    return render_template('admin_panel.html', user_profile=user_profile)

# c. 多角色檢查的使用場景:

@app.route('/editor')
@validate_tokens(required_role='editor,admin')  # 允許 "editor" 或 "admin" 訪問
def editor_page(user_profile):
    return render_template('editor.html', user_profile=user_profile)

# 6. 錯誤處理

當用戶未通過驗證或 Token 驗證失敗時,系統會返回一個對應的 HTML 頁面,並且會清除無效的 Cookie,讓用戶重新登錄。

  • 未登錄或 Cookie 丟失:返回 logout.html,用戶需重新登錄。
  • Access Token 無效:返回 Invalid_access_token.html,讓用戶重新授權。
  • Token 不一致:返回 Token_mismatch.html,並撤銷 Token。
  • ID Token 無效:返回 Invalid_or_expired_signed_token.html
  • 權限不足:返回 no_access.html

# 7. 測試與運行

  1. 配置 .env 或配置文件

    • 確保你有正確的 CLIENT_ID 和其他必要的配置,通常這些會存儲在環境變量或配置文件中。
  2. 運行 Flask 應用

    • 確保你正確設置了虛擬環境,並安裝了所有的依賴。
    • 執行 flask run 啟動你的應用程式,然後測試不同的路由,確認 Token 驗證邏輯是否按預期工作。

# 8. 結論

validate_tokens 是一個強大的裝飾器,可以保護你的 Flask 應用免於未授權的訪問。通過 Token 驗證和角色檢查,它確保只有正確身份和授權的用戶才能訪問某些路由。這個裝飾器可以輕鬆應用於任何需要基於權限管理的 Flask 應用程序中,並提供靈活的配置來應對不同場景下的安全需求。

# 相關依賴導入說明

# 1. ConfigManager

  • 來源from utils.config_manager import ConfigManager
  • 功能ConfigManager 是一個用於管理配置的模組。它主要用來從配置文件中讀取設置,例如 API 憑證、密鑰等敏感信息。在這個例子中,它被用來讀取 LINE API 的 CLIENT_ID
  • 使用場景
    • 它能夠幫助你將配置文件(如 .env.ini)中的配置信息讀取到你的應用程式中,而不需要在代碼中硬編碼這些信息。
    • 這樣可以保持安全性和靈活性,便於在不同環境中切換配置。
config_manager = ConfigManager()
CLIENT_ID = config_manager.get('LINE_API', 'CLIENT_ID')
  • 作用
    • config_manager.get('LINE_API', 'CLIENT_ID'):用來獲取你在配置文件中設定的 CLIENT_ID,該值通常用於驗證請求和身份驗證流程。
    • CLIENT_ID 是 LINE API 憑證,用來與 LINE 的 OAuth 服務進行交互。

# 2. UserManagement

  • 來源from utils.sql import UserManagement
  • 功能UserManagement 是一個與 SQLite 數據庫交互的模組,專門用於處理與用戶相關的操作。它負責管理用戶數據、權限、以及其他與用戶有關的數據庫操作。
  • 使用場景
    • 它提供了對用戶數據的增刪改查(CRUD)操作。
    • 當你需要驗證某個用戶是否擁有某個權限時,你可以使用這個模組與數據庫交互,來檢查用戶是否具備對應的角色。
user_mgmt = UserManagement('user_management.db')
  • 作用
    • user_mgmt = UserManagement('user_management.db'):初始化 UserManagement,並且指定數據庫的路徑(這裡是 user_management.db),這是 SQLite 數據庫文件,存儲用戶和權限的相關數據。
    • 這裡,你可以假設數據庫會包含用戶的基本資料以及其角色權限。

# 3. validate_signed_token

  • 來源from utils.token_utils import validate_signed_token
  • 功能validate_signed_token 是一個用於驗證 JWT(JSON Web Token)簽名的工具函數。它用來確保從 Cookie 中獲取的 signed_token 是有效的和未過期的。
  • 使用場景
    • 在登錄或驗證系統中,JWT 通常用來標識用戶的身份。每個 JWT 包含用戶的簽名和身份信息,服務器需要驗證該 Token 是否真實有效。
    • validate_signed_token 函數會解碼並檢查這個 Token,確保它的完整性和有效性。
signed_payload = validate_signed_token(jwt_token)
  • 作用
    • validate_signed_token(jwt_token):驗證來自 Cookie 的 jwt_token,確保該 Token 沒有被篡改且仍然有效。如果 Token 無效或過期,函數返回 None
    • 這樣你可以保證系統中的 Token 是安全的,防止未授權的用戶冒充。

# 4. revoke_tokens

  • 來源from utils.line_login_api import revoke_tokens
  • 功能revoke_tokens 是用來撤銷 LINE OAuth Token 的工具函數。當發現 access_tokenid_token 無效或過期時,會調用這個函數來使該 Token 作廢。
  • 使用場景
    • 當用戶登錄 Token 過期或者有安全風險時,你需要讓 LINE 停用該 Token。這樣可以防止潛在的安全威脅。
revoke_tokens(access_token)
  • 作用
    • revoke_tokens(access_token):告訴 LINE 停用該 access_token。如果 Token 無效或過期,此函數會確保該 Token 不能再被使用,並且讓用戶重新登錄以獲取新的 Token。

# 總結

  • ConfigManager:用於從配置文件中讀取 API 憑證,例如 CLIENT_ID
  • UserManagement:用於與數據庫交互,管理用戶的角色與權限。
  • validate_signed_token:驗證 JWT 簽名的有效性,確保 Token 的安全性。
  • revoke_tokens:撤銷過期或無效的 LINE OAuth Token,保護系統免於安全風險。
  • requests:發送 HTTP 請求來檢查 Token 的有效性,與外部 API(如 LINE)進行交互。

這些組件和函數共同合作,實現了用戶登錄狀態和權限的驗證,並確保 Token 安全有效。