一个简单的FastAPI认证示例

以下是一个简单的FastAPI认证示例:

from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from passlib.context import CryptContext
from datetime import datetime, timedelta
from jose import JWTError, jwt

app = FastAPI()

# 定义一些常量
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

# 定义密码哈希上下文
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

# 定义用户模型
class User:
    def __init__(self, username: str, hashed_password: str):
        self.username = username
        self.hashed_password = hashed_password

# 假设这是一个数据库,存储了一些用户信息
users_db = {
    "zeco": User("zeco", pwd_context.hash("password")),
    "jane": User("jane", pwd_context.hash("123456")),
}

# 定义获取用户的函数
def get_user(username: str):
    if username in users_db:
        return users_db[username]
    return None

# 定义验证密码的函数
def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)

# 定义创建访问令牌的函数
def create_access_token(data: dict, expires_delta: timedelta):
    to_encode = data.copy()
    expire = datetime.utcnow() + expires_delta
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

# 定义解析访问令牌的函数
def decode_access_token(access_token: str):
    try:
        payload = jwt.decode(access_token, SECRET_KEY, algorithms=[ALGORITHM])
        username = payload.get("sub")
        if username is None:
            raise JWTError
        return username
    except JWTError:
        raise HTTPException(status_code=401, detail="Invalid access token")

# 定义OAuth2密码模式
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token")

# 定义获取访问令牌的路由
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    user = get_user(form_data.username)
    if user is None:
        raise HTTPException(status_code=401, detail="Invalid username or password")
    if not verify_password(form_data.password, user.hashed_password):
        raise HTTPException(status_code=401, detail="Invalid username or password")
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}

# 定义需要认证的路由
@app.get("/protected")
async def protected_route(access_token: str = Depends(oauth2_scheme)):
    username = decode_access_token(access_token)
    return {"message": f"Hello, {username}!"}

以上代码中,我们使用了Passlib库来创建密码哈希上下文,并使用JWT库来创建和解析访问令牌。我们定义了一个简单的用户模型和一个假的数据库来存储用户信息。在登录时,我们会验证用户名和密码,并创建一个访问令牌,该令牌将在指定的时间后过期。在需要认证的路由中,我们使用Depends装饰器来指定OAuth2密码模式,并在访问令牌验证通过后返回受保护的响应。

你可能感兴趣的:(fastapi,python,开发语言)