FastAPI安全系列(一) OAuth2 .0認證基礎


一、介紹

OAuth2 .0模式有四種分別是:

  • 授權碼授權模式(Authorization Code Grant)
  • 隱式授權模式(Implicit Grant)
  • 密碼授權模式(Resource Owner Password Credential Grant)
  • 客戶端憑證授權模式(Client Credentials Grant)

這里探討的是第三種模式密碼授權模式(Resource Owner Password Credential Grant),這種模式的流程:

FastAPI中使用OAuth2來看一下它是如何使用工作的,然后來理解發生了什么。

from fastapi import Depends, FastAPI
from fastapi.security import OAuth2PasswordBearer

app = FastAPI()

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")


@app.get("/items/")
async def read_items(token: str = Depends(oauth2_scheme)):
    return {"token": token}

訪問 http://127.0.0.1:8000/docs#/

 在路徑操作的右上角有一個可以點擊的鎖,如果你點擊它,你會得到一個由username和password(以及其它的可選字段)的認證的表單。

現在理解一下這個流程:

  • 在前端輸入用戶的username和password
  • 前台將用username和password發送給后台一個特殊API的URL(通過tokenUrl="token"聲明的)
  • 這個特殊的API檢查username和password,然后返回一個“token”,在下次請求時將會通過這個token進行用戶驗證,正常的是這個token是有過期時間的
  • 這個token前端會臨時存儲在某個地方
  • 然后每次請求時會攜帶一個Authorization的請求頭
  • 后台會檢查Authorization請求頭中是否有token值,如果沒有,直接返回401狀態碼以及UNAUTHORIZED錯誤信息

FastAPI在不同的抽象級別提供了幾個工具,用來實現這些安全特性。

 二、OAuth2PasswordBearer

1、參數說明

 當我們通過OAuth2PasswordBearer類來創建一個實例,並且通過tokenUrl參數傳遞一個URL,客戶端將會將username和password傳遞到這個URL對應的路徑操作函數中,然后得到一個token。

...
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
...

此處的tokenUrl="token"是相對路徑,相當於tokenUrl="./token"。

oauth2_schemes實例變量是可調用的,這就意味着它可以作為依賴項。所以在路徑操作函數中:

...
@app.get("/items/")
async def read_items(token: str = Depends(oauth2_scheme)):
    return {"token": token}
...

  這個依賴項提供一個str用來標記路徑操作函數的token參數。FastAPI知道它可以使用這個依賴在OpenAPI中來定義一個“安全模式”(以及自動交互的API文檔)。

 2、獲取當前用戶

上述基於安全系統向路徑操作函數提供了一個str類型的token,但這並不是很實用,實際上可以使它返回當前的用戶信息。

  •  創建用戶模型
from typing import Optional
from pydantic import BaseModel

class User(BaseModel):
    username: str
    email: Optional[str] = None
    full_name: Optional[str] = None
    disabled: Optional[bool] = None
  • 創建get_current_user依賴項

此時可以將oauth2_scheme 作為get_current_user的依賴項,然后將get_current_user作為路徑操作函數的依賴項。

...
async def get_current_user(token: str = Depends(oauth2_scheme)):
    pass


@app.get("/users/me")
async def read_users_me(current_user: User = Depends(get_current_user)):
    return current_user
...
  • 獲取用戶
...
def fake_decode_token(token): return User( username=token + "fakedecoded", email="john@example.com", full_name="John Doe" ) async def get_current_user(token: str = Depends(oauth2_scheme)): user = fake_decode_token(token) return user
...
  • 注入當前用戶
...
@app.get("/users/me")
async def read_users_me(current_user: User = Depends(get_current_user)):
    return current_user
...

3、完整代碼

from typing import Optional
from fastapi import Depends, FastAPI
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel

app = FastAPI()

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")


class User(BaseModel):
    username: str
    email: Optional[str] = None
    full_name: Optional[str] = None
    disabled: Optional[bool] = None


def fake_decode_token(token):
    return User(
        username=token + "fakedecoded", email="john@example.com", full_name="John Doe"
    )


async def get_current_user(token: str = Depends(oauth2_scheme)):
    user = fake_decode_token(token)
    return user


@app.get("/users/me")
async def read_users_me(current_user: User = Depends(get_current_user)):
    return current_user

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM