使用者狀態管理
FastAPI 可使用 Starlette 提供的 `SessionMiddleware` 管理使用者狀態。它會將 Session 資料放在 Cookie 中,並使用 `secret_key` 簽章,之後透過 `request.session` 讀寫。
## 安裝
```bash
pip install fastapi uvicorn
```
## 簡單範例
```python
import os
from fastapi import FastAPI, Request, HTTPException
from pydantic import BaseModel
from starlette.middleware.sessions import SessionMiddleware
app = FastAPI()
# 正式環境應使用環境變數或密鑰管理服務提供 secret_key
app.add_middleware(
SessionMiddleware,
secret_key=os.getenv("SESSION_SECRET", "dev-secret-change-me"),
session_cookie="my_session",
max_age=60 * 60 * 24 * 7, # Session 有效期:7 天
same_site="lax",
https_only=False, # 正式環境使用 HTTPS 時建議設為 True
)
class LoginData(BaseModel):
username: str
password: str
# 假設的使用者資料
USERS = {
"alice": "123456",
}
@app.post("/login")
async def login(data: LoginData, request: Request):
password = USERS.get(data.username)
if password is None or password != data.password:
raise HTTPException(status_code=401, detail="帳號或密碼錯誤")
# 登入前清除舊的 Session,避免 Session Fixation
request.session.clear()
# 將使用者資訊寫入 Session
request.session["user_id"] = data.username
return {
"message": "登入成功",
"user_id": data.username,
}
@app.get("/me")
async def get_current_user(request: Request):
# 從 Session 讀取使用者資訊
user_id = request.session.get("user_id")
if user_id is None:
raise HTTPException(status_code=401, detail="尚未登入")
return {
"user_id": user_id,
"logged_in": True,
}
@app.post("/logout")
async def logout(request: Request):
# 清除目前的 Session
request.session.clear()
return {"message": "已登出"}
```
啟動:
```bash
uvicorn main:app --reload
```
登入:
```bash
curl -c cookies.txt \
-X POST http://127.0.0.1:8000/login \
-H "Content-Type: application/json" \
-d '{"username":"alice","password":"123456"}'
```
查詢目前使用者:
```bash
curl -b cookies.txt http://127.0.0.1:8000/me
```
登出:
```bash
curl -b cookies.txt -X POST http://127.0.0.1:8000/logout
```
## 注意事項
- `request.session` 本質上是一個類似字典的物件,可以存取字串、數字等可序列化資料。
- `SessionMiddleware` 預設是將 Session 資料儲存在瀏覽器 Cookie 中,而不是伺服器資料庫。
- Cookie 內容通常是「簽章」而非加密,因此不要放入密碼、Token 或其他敏感資料。
- `secret_key` 必須使用足夠隨機且不公開的值。
- 正式環境建議設定:
```python
https_only=True
```
這會要求 Cookie 只能透過 HTTPS 傳送。Cookie 也會自動帶有 `HttpOnly` 屬性,降低 JavaScript 直接讀取 Cookie 的風險。
相關學習地圖、教學課程
Python 後端工程、資料庫