首頁 後端開發 Python教學 具有依賴注入的 FastAPI 身份驗證

具有依賴注入的 FastAPI 身份驗證

Sep 24, 2024 am 06:21 AM

FastAPI Auth with Dependency Injection

FastAPI 是一個用於在 Python 中建立 API 的現代 Web 框架。它是我個人最喜歡的 Web 框架之一,因為它內建了對 OpenAPI 規範的支援(這意味著您可以編寫後端程式碼並從中生成所有內容),並且它支援依賴注入

在這篇文章中,我們將簡要介紹一下 FastAPI 的 Depends 是如何運作的。然後我們將了解為什麼它如此適用於身份驗證和授權。我們還將它與中間件進行對比,中間件是身份驗證的另一個常見選項。最後,我們將了解 FastAPI 中一些更進階的授權模式。

什麼是依賴注入?

FastAPI 更強大的功能之一是它對依賴注入的一流支援。我們有一個更長的指南這裡,但讓我們來看一個如何使用它的快速範例。

假設我們正在建立一個分頁 API。每個API呼叫可以包括page_number和page_size。現在,我們可以建立一個 API 並直接傳入這些參數:

@app.get("/things/")
async def fetch_things(page_number: int = 0, page_size: int = 100):
    return db.fetch_things(page_number, page_size)
登入後複製

但是,我們可能想要加入一些驗證邏輯,這樣就沒有人要求 page_number -1 或 page_size 10,000,000。

@app.get("/things/")
async def fetch_things(page_number: int = 0, page_size: int = 100):
    if page_number < 0:
        raise HTTPException(status_code=400, detail="Invalid page number")
    elif page_size <= 0:
        raise HTTPException(status_code=400, detail="Invalid page size")
    elif page_size > 100:
        raise HTTPException(status_code=400, detail="Page size can be at most 100")
    return db.fetch_things(page_number, page_size)
登入後複製

這…很好,但如果我們有 10 個 API 或 100 個 API 都需要相同的分頁參數,那就有點無聊了。這就是依賴注入的用武之地 - 我們可以將所有這些邏輯移至一個函數中,並將該函數注入到我們的 API 中:

async def paging_params_dep(page_number: int = 0, page_size: int = 100):
    if page_number < 0:
        raise HTTPException(status_code=400, detail="Invalid page number")
    elif page_size <= 0:
        raise HTTPException(status_code=400, detail="Invalid page size")
    elif page_size > 100:
        raise HTTPException(status_code=400, detail="Page size can be at most 100")
    return PagingParams(page_number, page_size)

@app.get("/things/")
async def fetch_things(paging_params: PagingParams = Depends(paging_params_dep)):
    return db.fetch_things(paging_params)

@app.get("/other_things/")
async def fetch_other_things(paging_params: PagingParams = Depends(paging_params_dep)):
    return db.fetch_other_things(paging_params)
登入後複製

這有一些不錯的好處:

  • 每條採用 PagingParams 的路由都會自動驗證並具有預設值。

  • 它比每條路由的第一行是 validate_paging_params(page_number, page_size)

  • 更簡潔,更容易出錯
  • 這仍然適用於 FastAPI 的 OpenAPI 支援 - 這些參數會顯示在您的 OpenAPI 規格中。

這與身分驗證有什麼關係?

事實證明,這也是一種建模身份驗證的好方法!想像你有一個像這樣的函數:

async def validate_token(token: str):
    try:
        # This could be JWT validation, looking up a session token in the DB, etc.
        return await get_user_for_token(token)
    except:
        return None
登入後複製

要將其連接到 API 路由,我們需要做的就是將其包裝在依賴項中:

async def require_valid_token_dep(req: Request):
    # This could also be a cookie, x-api-key header, etc.
    token = req.headers["Authorization"]
    user = await validate_token(token)
    if user == None:
        raise HTTPException(status_code=401, detail="Unauthorized")
    return user
登入後複製

然後我們所有受保護的路由都可以添加此依賴項:

@app.get("/protected")
async def do_secret_things(user: User = Depends(require_valid_token_dep)):
    # do something with the user
登入後複製

如果使用者提供了有效的令牌,則該路由將運行並設定使用者。否則,將返回 401。

注意:OpenAPI/Swagger 確實對指定身份驗證令牌具有一流的支持,但您必須使用其中一個專用類別。您可以使用 fastapi.security 中的 HTTPBearer(auto_error=False) 來取代 req.headers["Authorization"],它會傳回 HTTPAuthorizationCredentials。

中介軟體與 Depends for Auth

FastAPI 與大多數框架一樣,有一個中間件 的概念。您的中間件可以包含將在請求之前和之後運行的程式碼。它可以在請求到達您的路由之前修改請求,也可以在回應傳回給使用者之前修改回應。

在許多其他框架中,中間件是進行身份驗證檢查的非常常見的地方。然而,這通常是因為中間件也負責將使用者「注入」到路由中。例如,Express 中的常見模式是執行以下操作:

app.get("/protected", authMiddleware, (req, res) => {
    // req.user is set by the middleware
    // as there's no good way to pass in extra information into this route,
    // outside of the request
});
登入後複製

由於FastAPI具有內建的注入概念,因此您可能根本不需要使用中介軟體。如果您需要定期「刷新」您的身份驗證令牌(以使其保持活動狀態)並將回應設定為 cookie,我會考慮使用中間件。

在這種情況下,您需要使用 request.state 將資訊從中間件傳遞到路由(如果您願意,您可以使用依賴項來驗證 request.state)。

否則,我會堅持使用 Depends,因為用戶將直接注入到您的路由中,而不需要通過 request.state。

授權 - 多租用戶、角色和權限

如果我們應用迄今為止所學到的一切,添加多租戶、角色或權限可能會非常簡單。假設我們為每個客戶都有一個唯一的子網域,我們可以為該子網域建立依賴關係:

async def tenant_by_subdomain_dep(request: Request) -> Optional[str]:
    # first we get the subdomain from the host header
    host = request.headers.get("host", "")
    parts = host.split(".")
    if len(parts) <= 2:
        raise HTTPException(status_code=404, detail="Not found")
    subdomain = parts[0]

    # then we lookup the tenant by subdomain
    tenant = await lookup_tenant_for_subdomain(subdomain)
    if tenant == None:
        raise HTTPException(status_code=404, detail="Not found")
    return tenant

登入後複製

我們可以將這個想法與先前的想法結合起來,製作一個新的「多租戶」依賴:

async def get_user_and_tenant_for_token(
    user: User = Depends(require_valid_token_dep),
    tenant: Tenant = Depends(tenant_by_subdomain_dep),
) -> UserAndTenant:
    is_user_in_tenant = await check_user_is_in_tenant(tenant, user)
    if is_user_in_tenant:
        return UserAndTenant(user, tenant)
    raise HTTPException(status_code=403, detail="Forbidden")
登入後複製

然後我們可以將此依賴項注入到我們的路由中:

@app.get("/protected")
async def do_secret_things(user_and_tenant: UserAndTenant = Depends(get_user_and_tenant_for_token)):
    # do something with the user and tenant
登入後複製

這最終會做一些主要的事情:

  • 檢查使用者是否擁有有效令牌

  • 檢查使用者是否正在向有效的子網域發出請求

  • 檢查使用者是否應該有權利存取該子網域

If any of those invariants aren’t met - an error is returned and our route will never run. We can extend this to include other things like roles & permissions (RBAC) or making sure the user has a certain property set (active paid subscription vs no active subscription).

PropelAuth <3 FastAPI

At PropelAuth, we’re big fans of FastAPI. We have a FastAPI library that will enable you to set up authentication and authorization quickly - including SSO, Enterprise SSO / SAML, SCIM Provisioning, and more.

And it all works with dependencies like the ones you’ve seen above, e.g.:

@app.get("/")
async def root(current_user: User = Depends(auth.require_user)):
    return {"message": f"Hello {current_user.user_id}"}
登入後複製

You can find out more here.

Summary

  • FastAPI's dependency injection provides a powerful way to handle authentication and authorization in web applications.

  • The Depends feature allows for clean, reusable code for validating tokens, checking user permissions, and handling multi-tenancy.

  • Compared to middleware, using dependencies for auth offers more flexibility and direct integration with route functions.

  • Complex authorization scenarios like multi-tenancy and role-based access control can be efficiently implemented using nested dependencies.

  • PropelAuth offers a FastAPI library that simplifies the implementation of advanced authentication and authorization features.

以上是具有依賴注入的 FastAPI 身份驗證的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1422
52
Laravel 教程
1316
25
PHP教程
1267
29
C# 教程
1239
24
Python vs.C:申請和用例 Python vs.C:申請和用例 Apr 12, 2025 am 12:01 AM

Python适合数据科学、Web开发和自动化任务,而C 适用于系统编程、游戏开发和嵌入式系统。Python以简洁和强大的生态系统著称,C 则以高性能和底层控制能力闻名。

Python:遊戲,Guis等 Python:遊戲,Guis等 Apr 13, 2025 am 12:14 AM

Python在遊戲和GUI開發中表現出色。 1)遊戲開發使用Pygame,提供繪圖、音頻等功能,適合創建2D遊戲。 2)GUI開發可選擇Tkinter或PyQt,Tkinter簡單易用,PyQt功能豐富,適合專業開發。

2小時的Python計劃:一種現實的方法 2小時的Python計劃:一種現實的方法 Apr 11, 2025 am 12:04 AM

2小時內可以學會Python的基本編程概念和技能。 1.學習變量和數據類型,2.掌握控制流(條件語句和循環),3.理解函數的定義和使用,4.通過簡單示例和代碼片段快速上手Python編程。

Python與C:學習曲線和易用性 Python與C:學習曲線和易用性 Apr 19, 2025 am 12:20 AM

Python更易學且易用,C 則更強大但複雜。 1.Python語法簡潔,適合初學者,動態類型和自動內存管理使其易用,但可能導致運行時錯誤。 2.C 提供低級控制和高級特性,適合高性能應用,但學習門檻高,需手動管理內存和類型安全。

您可以在2小時內學到多少python? 您可以在2小時內學到多少python? Apr 09, 2025 pm 04:33 PM

兩小時內可以學到Python的基礎知識。 1.學習變量和數據類型,2.掌握控制結構如if語句和循環,3.了解函數的定義和使用。這些將幫助你開始編寫簡單的Python程序。

Python和時間:充分利用您的學習時間 Python和時間:充分利用您的學習時間 Apr 14, 2025 am 12:02 AM

要在有限的時間內最大化學習Python的效率,可以使用Python的datetime、time和schedule模塊。 1.datetime模塊用於記錄和規劃學習時間。 2.time模塊幫助設置學習和休息時間。 3.schedule模塊自動化安排每週學習任務。

Python:自動化,腳本和任務管理 Python:自動化,腳本和任務管理 Apr 16, 2025 am 12:14 AM

Python在自動化、腳本編寫和任務管理中表現出色。 1)自動化:通過標準庫如os、shutil實現文件備份。 2)腳本編寫:使用psutil庫監控系統資源。 3)任務管理:利用schedule庫調度任務。 Python的易用性和豐富庫支持使其在這些領域中成為首選工具。

Python:探索其主要應用程序 Python:探索其主要應用程序 Apr 10, 2025 am 09:41 AM

Python在web開發、數據科學、機器學習、自動化和腳本編寫等領域有廣泛應用。 1)在web開發中,Django和Flask框架簡化了開發過程。 2)數據科學和機器學習領域,NumPy、Pandas、Scikit-learn和TensorFlow庫提供了強大支持。 3)自動化和腳本編寫方面,Python適用於自動化測試和系統管理等任務。

See all articles