今天是這個簡易庫存系統的最後一天,我們用 Cookies 搭配 JWT 的實作來做個收尾。每個專案對於 jwt 的做法都不同,有的專案可能會分為長時效的 refresh token 和短時效的 access token 兩種 token之類的作法,這個時候除了在 memory 中存放 token 外,或許也會放在 Session 或 Cookies 中,我們這章便著重於介紹如何在 FastAPI 使用 Cookies。
是一種在網站和網頁之間傳遞資訊的機制,它在瀏覽器和伺服器之間儲存少量數據,以便識別用戶、記住用戶的狀態,以及執行其他與網站互動相關的功能。Cookies 在網站的使用中非常常見,幾乎每次你訪問一個網站,瀏覽器都會處理和傳遞 Cookies。但使用時要注意,不要把敏感資料儲存在 Cookies 中。
FastAPI 可以在 Response 中設置 Cookies,也可以在路徑操作函式中聲明要拿取 Cookies,接下來我們將改寫顧客登入與拿取顧客資料作為範例講解。
# src/main.py
from fastapi import FastAPI, status, Depends, Response
@app.post("/login", response_model=schemas.LoginReturn)
def login(
response: Response,
customer: models.Customer = Depends(dependencies.authenticate_customer),
):
"""
Login
"""
access_token = jwt.create_access_token(
data={"sub": customer.id, "mail": customer.mail}
)
customer.token = access_token
response.set_cookie(key="access_token", value=access_token, httponly=True)
return customer
我們使用 fastapi 中的 Response,並在路徑操作函式中聲明該物件,這樣我們就可以在函式裡對要返回給用戶端的回應進行操作設置。
接著我們就可以使用 response.set_cookie
來對用戶端設置 cookies,為了避免 cookies 遭到用戶端惡意程式碼存取,我們將 httponly 設置為 True,增強保護。
登入成功後,可以使用瀏覽器的開發人員工具看到 cookies 確實地被設置進去了。
# src/jwt.py
from fastapi import Cookie
async def decode_jwt(access_token: str = Cookie(default=None)) -> dict:
if access_token is None:
raise exceptions.CredentialsDataWrong()
try:
payload = jwt.decode(access_token, SECRET_KEY, algorithms=[ALGORITHM])
id: str = payload.get("sub")
if id is None:
raise exceptions.CredentialsDataWrong()
except JWTError:
raise exceptions.CredentialsDataWrong()
return payload
透過使用 fastapi 中的 Cookie 聲明引入參數,便可以從 cookies 中獲取對應 key 的值。
我們修改 decode_jwt
的引入參數改為 access_token,等等就可以獲取到 cookies 中的 access_token。
使用 access_token: str = Cookie(default=None)
這種寫法可以讓 FastAPI 知道要從 Cookies 中獲取資料的同時,也可以讓他去驗證資料型態是否正確。記得在拿不到 Cookie 的時候要 raise 錯誤回應用戶端。
如果沒有 Cookie 的情況會獲得上圖中的回應。
有成功獲取到 Cookie 中的 access token 的話便能成功或取顧客資料。
我們簡易庫存系統就到這裡告一段落,接下來的重點將會放在介紹 FastAPI 與其他軟體的集成上或是更進階的 API 操作。
若是後續的介紹中有覺得可以將其整併到這個系統中的東西,大家也不妨自己動手練習看看將其整合到這個簡易系統中。
Cookie 参数 - FastAPI (tiangolo.com)
响应Cookies - FastAPI (tiangolo.com)