裝飾器 validate_tokens 完整使用手冊
# 目錄
- 簡介
- 使用說明
- 依賴項目
- 驗證邏輯解釋
- 裝飾器的詳細使用
- 錯誤處理
- 測試與運行
- 結論
# 1. 簡介
validate_tokens
是一個用於 Flask 的裝飾器,能夠幫助你驗證用戶的登入狀態與角色權限。它通過檢查 LINE 的 access_token
和 id_token
,來確認用戶是否已登入以及是否擁有訪問某些頁面的權限。裝飾器提供了靈活的配置,允許你指定角色來限制不同用戶的權限,並且處理 Token 過期或不一致的情況。
# 2. 使用說明
要使用 validate_tokens
裝飾器,你需要將它應用於 Flask 路由中,用來保護需要登入和/或擁有特定角色的頁面。這個裝飾器主要針對 API Token 驗證,因此使用的是基於 Cookie 的 access_token
和 id_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_token
和id_token
是否有效。- 安裝:
pip install requests
- 安裝:
utils 模組:
- ConfigManager:用於管理配置,從配置檔案中獲取
CLIENT_ID
等關鍵值。 - validate_signed_token:用於驗證簽名 Token,確保 Token 的有效性。
- revoke_tokens:在 Token 無效或過期時,撤銷用戶的 Token。
- UserManagement:用於操作用戶數據庫,如檢查用戶的角色權限。
- ConfigManager:用於管理配置,從配置檔案中獲取
# 裝飾器中需要的模組:
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
的工作流程如下:
檢查 Cookie:
- 首先,從用戶的 Cookie 中獲取
access_token
、id_token
和signed_token
。 - 如果任意一個缺失,則跳轉到登出頁面並清除 Cookie。
- 首先,從用戶的 Cookie 中獲取
驗證 Access Token:
- 使用
access_token
向 LINE 的 API 發送請求,檢查用戶是否已經登入。 - 如果 Token 無效,則返回 "Invalid Access Token" 錯誤並清除 Token。
- 使用
檢查簽名 Token 一致性:
- 使用
validate_signed_token
驗證 JWT Token 的有效性。 - 驗證 Token 中的
access_token
和id_token
是否與 Cookie 中的值匹配。 - 如果不一致,則撤銷 Token 並跳轉到 "Token Mismatch" 頁面。
- 使用
ID Token 驗證:
- 使用
id_token
向 LINE 的驗證服務請求,確認用戶身份是否有效。 - 如果無效,返回 "Invalid ID Token" 錯誤。
- 使用
角色權限檢查:
- 如果指定了
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. 測試與運行
配置
.env
或配置文件:- 確保你有正確的
CLIENT_ID
和其他必要的配置,通常這些會存儲在環境變量或配置文件中。
- 確保你有正確的
運行 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_token
或id_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 安全有效。