FastAPI系列:自定义认证

from typing import Optional, Tuple

from fastapi import FastAPI, Request
from pydantic import BaseModel
# 通过starlette.authentication导入AuthenticationBackend
from starlette.authentication import AuthenticationBackend, AuthenticationError, AuthCredentials, SimpleUser, requires
from starlette.middleware import Middleware
from starlette.middleware.authentication import AuthenticationMiddleware
from starlette.requests import HTTPConnection

class UserReq(BaseModel):
    username: str
    password: str

class UsernameAuthBackend(AuthenticationBackend):
    keyword = 'bearer'

    def __init__(self, username):
        self.username = username
    # 必须实现该方法,而且必须async修饰
    async def authenticate(self, request):
        """源码
        async def authenticate(
        self, conn: HTTPConnection  # 传入HTTP连接的基类,用于提供 Request 和 WebSocket 通用的任何功能。
    ) -> typing.Optional[typing.Tuple["AuthCredentials", "BaseUser"]]:
        raise NotImplementedError()  # pragma: no cover
        """
        if "Authorization" not in request.headers:
            return

        auth = request.headers["Authorization"]
        print(auth)
        try:
            scheme, username = auth.split()
            if scheme.lower().strip() != self.keyword.strip():
                return
        except:
            raise AuthenticationError('Invalid basic auth credentials')
        if not username == self.username:
            return
        # authenticate方法必须返回AuthCredentials和BaseUser,AuthCredentials必须是用列表嵌套字符串的形式,
        return AuthCredentials(["authenticated"]), SimpleUser(username)


middleware = [Middleware(AuthenticationMiddleware, backend=UsernameAuthBackend("liuwei"))]

app = FastAPI(middleware=middleware)


@requires("authenticated")
@app.get("/login")
def login(user: UserReq, request: Request):
    return user

posted @ 2024-02-28 18:42  我在路上回头看  阅读(220)  评论(0编辑  收藏  举报