API接口文档中实现OAuth2认证,OAuth不是一个API或者服务,而是一个认证授权(Authorization)的开放标准。
自定义OAuth2PasswordBearer
在fastapi中,官方提供了OAuth2PasswordBearer依赖。可以在接口文档中出现认证的图标。
接口文档中出现了需要认证图标的示例代码:
from typing import Unionimport uvicorn
from fastapi import Depends, FastAPI
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModelapp = FastAPI()oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")class User(BaseModel):username: stremail: Union[str, None] = Nonefull_name: Union[str, None] = Nonedisabled: Union[bool, None] = Nonedef 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_userif __name__ == '__main__':uvicorn.run(app,)
编写oauth2.py文件
自定义OAuth2认证,继承FastAPI框架的OAuth2PasswordBearer,实现自身业务的认证机制。
from typing import Optionalfrom fastapi import HTTPException
from fastapi.security import OAuth2PasswordBearer
from fastapi.security.utils import get_authorization_scheme_param
from starlette.requests import Request
from starlette.status import HTTP_401_UNAUTHORIZEDfrom config import settingsclass OAuth2(OAuth2PasswordBearer):"""对于doc文档中需要登录后才能访问的API接口,需要添加OAuth2PasswordBearer依赖项自定义此类,并继承OAuth2PasswordBearer,重写父类的call方法,实现自身业务的token验证"""def __init__(self, tokenUrl: str, schema: str):""":param tokenUrl: 接口文档中,表单提交请求的路由:param schema: Token的实现技术,本项目中采用JWT"""super().__init__(tokenUrl, schema)async def __call__(self, request: Request) -> Optional[str]:"""解析请求头中的 token:param request::return:"""path:str = request.url.path# 如果请求地址不在 no_access_token_urls 中,则需要token令牌验证if path not in settings.no_access_token_urls:authorization = request.headers.get("Authorization")scheme, param = get_authorization_scheme_param(authorization)if not authorization or scheme.lower() != "bearer":if self.auto_error:raise HTTPException(status_code=HTTP_401_UNAUTHORIZED,detail="Not authenticated",headers={"WWW-Authenticate": "Bearer"},)else:return Nonereturn paramelse:return ''
编写docs文档中的Token认证接口
docs_routers.py
from fastapi import APIRouter, Depends
from fastapi.security import OAuth2PasswordRequestFormfrom apps.docs_auth.exceptions.docs_exception import DocsTokenFromNotNullException
from utils.jwt import JWTdocs = APIRouter()@docs.post("/token", summary="API接口文档的Token认证")
async def docs_token(from_data: OAuth2PasswordRequestForm = Depends()):""":param from_data::return:"""username = from_data.usernamepassword = from_data.passwordif not username or not password:raise DocsTokenFromNotNullExceptionreturn {"token_type": "bearer","access_token": JWT.create_access_token(username)}
main.py 需要修改添加的代码
# 添加自定义的接口文档OAuth2实现
oauth2 = OAuth2(tokenUrl="/docs/token", schema="JWT")# exception_handlers : 异常处理器
# dependencies : 全局依赖 依赖项->oauth2
app = FastAPI(exception_handlers=my_exception_handlers, dependencies=[Depends(oauth2)])# 注册路由
app.include_router(docs, prefix="/docs", tags=["docs文档Token认证"])
然后,访问接口文档