假設(shè)您在某個(gè)域中擁有后端API。
并且您在另一個(gè)域或同一域的不同路徑(或移動(dòng)應(yīng)用程序)中有一個(gè)前端。
并且您希望有一種方法讓前端使用用戶名和密碼與后端進(jìn)行身份驗(yàn)證。
我們可以使用OAuth2通過(guò)FastAPI來(lái)構(gòu)建它。
但是讓我們節(jié)省您閱讀完整的長(zhǎng)規(guī)范的時(shí)間,只是為了找到您需要的那些小信息。
讓我們使用FastAPI提供的工具來(lái)處理安全性。
讓我們首先使用代碼看看它是如何工作的,然后我們會(huì)回來(lái)了解發(fā)生了什么。
將示例復(fù)制到文件中main.py:
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}
信息
首先安裝python-multipart.
例如pip install python-multipart。
這是因?yàn)镺Auth2使用“表單數(shù)據(jù)”來(lái)發(fā)送username和password。
使用以下命令運(yùn)行示例:
uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
核實(shí)
轉(zhuǎn)到交互式文檔:http : //127.0.0.1 : 8000/ docs 。
你會(huì)看到這樣的事情:
授權(quán)按鈕!
您已經(jīng)有了一個(gè)閃亮的新“授權(quán)”按鈕。
并且您的路徑操作在右上角有一個(gè)小鎖,您可以單擊它。
如果你點(diǎn)擊它,你會(huì)有一個(gè)小的授權(quán)表格來(lái)輸入一個(gè)username和password(和其他可選字段):
筆記
無(wú)論您在表單中輸入什么,它都不會(huì)起作用。但我們會(huì)到達(dá)那里。
這當(dāng)然不是最終用戶的前端,但它是一個(gè)很好的自動(dòng)工具,可以交互式地記錄所有 API。
它可以被前端團(tuán)隊(duì)使用(也可以是你自己)。
它可以被第三方應(yīng)用程序和系統(tǒng)使用。
它也可以由您自己使用,調(diào)試、檢查和測(cè)試相同的應(yīng)用程序。
現(xiàn)在讓我們回過(guò)頭來(lái)了解這一切。
在password“流”是的方法之一(“流”)中的OAuth2所定義,手柄安全性和認(rèn)證。
OAuth2 旨在使后端或 API 可以獨(dú)立于對(duì)用戶進(jìn)行身份驗(yàn)證的服務(wù)器。
但在這種情況下,同一個(gè)FastAPI應(yīng)用程序?qū)⑻幚?API 和身份驗(yàn)證。
所以,讓我們從簡(jiǎn)化的角度來(lái)回顧一下:
FastAPI提供了幾種不同抽象級(jí)別的工具來(lái)實(shí)現(xiàn)這些安全功能。
在此示例中,我們將使用OAuth2和密碼流,使用不記名令牌。我們使用OAuth2PasswordBearer類(lèi)來(lái)做到這一點(diǎn)。
信息
“承載”令牌不是唯一的選擇。
但這對(duì)我們的用例來(lái)說(shuō)是最好的。
它可能是大多數(shù)用例的最佳選擇,除非您是 OAuth2 專家并且確切地知道為什么有另一種選擇更適合您的需求。
在這種情況下,F(xiàn)astAPI還為您提供了構(gòu)建它的工具。
當(dāng)我們創(chuàng)建OAuth2PasswordBearer類(lèi)的實(shí)例時(shí),我們傳入tokenUrl參數(shù)。此參數(shù)包含客戶端(在用戶瀏覽器中運(yùn)行的前端)將用于發(fā)送username和password以獲取令牌的 URL 。
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}
提示
這里tokenUrl="token"指的token是我們尚未創(chuàng)建的相對(duì) URL 。因?yàn)樗且粋€(gè)相對(duì) URL,所以它相當(dāng)于./token.
因?yàn)槲覀兪褂玫氖窍鄬?duì) URL,如果您的 API 位于https://example.com/,那么它將引用https://example.com/token。但是如果您的 API 位于https://example.com/api/v1/,那么它將引用https://example.com/api/v1/token.
使用相對(duì) URL 很重要,以確保您的應(yīng)用程序即使在像Beyond a Proxy這樣的高級(jí)用例中也能繼續(xù)工作。
此參數(shù)不會(huì)創(chuàng)建該端點(diǎn)/路徑操作,而是聲明該 URL/token將是客戶端應(yīng)用于獲取令牌的 URL 。該信息在 OpenAPI 中使用,然后在交互式 API 文檔系統(tǒng)中使用。
我們很快也會(huì)創(chuàng)建實(shí)際的路徑操作。
信息
如果您是一個(gè)非常嚴(yán)格的“Pythonista”,您可能會(huì)不喜歡參數(shù)名稱tokenUrl而不是token_url.
那是因?yàn)樗褂门c OpenAPI 規(guī)范中相同的名稱。因此,如果您需要對(duì)這些安全方案中的任何一個(gè)進(jìn)行更多調(diào)查,您只需復(fù)制并粘貼它即可找到有關(guān)它的更多信息。
該oauth2_scheme變量是 的一個(gè)實(shí)例OAuth2PasswordBearer,但它也是一個(gè)“可調(diào)用的”。
它可以被稱為:
oauth2_scheme(some, parameters)
因此,它可以與Depends.
現(xiàn)在你可以oauth2_scheme在依賴中傳遞它Depends。
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}
這種依賴性將提供一個(gè)str被分配給所述參數(shù)token的的路徑操作功能。
FastAPI將知道它可以使用此依賴項(xiàng)在 OpenAPI 模式(和自動(dòng) API 文檔)中定義“安全方案”。
技術(shù)細(xì)節(jié)
FastAPI會(huì)知道它可以使用類(lèi)OAuth2PasswordBearer(在依賴項(xiàng)中聲明)來(lái)定義 OpenAPI 中的安全方案,因?yàn)樗^承自fastapi.security.oauth2.OAuth2,而后者又繼承自fastapi.security.base.SecurityBase。
所有與 OpenAPI(和自動(dòng) API 文檔)集成的安全實(shí)用程序都繼承自SecurityBase,這就是FastAPI知道如何將它們集成到 OpenAPI 的方式。
它將查看該Authorization標(biāo)頭的請(qǐng)求,檢查該值是否Bearer加上一些令牌,并將令牌作為str.
如果它沒(méi)有看到Authorization標(biāo)題,或者值沒(méi)有Bearer標(biāo)記,它將UNAUTHORIZED直接以 401 狀態(tài)代碼錯(cuò)誤 ( )響應(yīng)。
您甚至不必檢查令牌是否存在即可返回錯(cuò)誤。您可以確定,如果您的函數(shù)被執(zhí)行,它將str在該令牌中包含一個(gè)。
您可以在交互式文檔中嘗試它:
我們還沒(méi)有驗(yàn)證令牌的有效性,但這已經(jīng)是一個(gè)開(kāi)始。
因此,只需 3 或 4 行額外的行,您就已經(jīng)擁有某種原始形式的安全性。
更多建議: