You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI如何为后续请求添加Authorization请求头

API认证功能问题排查与解决

问题背景

我正在开发API的认证功能,实现了/login端点可以正常生成Token,但后续访问需要认证的/register端点时,请求未携带Authorization头导致认证失败。同时想知道Swagger UI的“Authorize”按钮如何自动携带Authorization头。

登录端点代码

@router.get("/login")
def login(request: Request):
    return templates.TemplateResponse("auth/login.html", {"request": request})


@router.post("/login")
def login(
    request: Request,
    username: str = Form(...),
    password: str = Form(...),

):
    errors = []
    user_db = pd.read_excel('users.xlsx')
    user = authenticate_user(user_db=user_db, username=username, password=password)

    access_token = create_access_token(data={"sub": username})

    response.set_cookie(
        key="access_token", value=f"Bearer {access_token}", httponly=True
    )
    response.headers['Authorization'] = f"Bearer {access_token}"
    return response

注册端点代码

@router.get("/register")
def register(request: Request,
             access_token: Annotated[Union[str, None], Cookie()] = None
             ):
    # print(access_token)
    #print(request.headers['Authorization'])
    return templates.TemplateResponse("auth/register.html", {"request": request})


@router.post("/register")
def register(
    request: Request,
    current_user: Annotated[User, Depends(get_current_active_user)], # 此处认证失败
    username: str = Form(...),
    password: str = Form(...),
    password_confirm: str = Form(...),


):

    print(current_user)

    try:
        user = UserCreate(username=username, password=password, password_confirm=password_confirm,
                          superuser = False)
        if current_user.superuser:
            message = crear_usuario(user=user)
            return JSONResponse(content={'message': message})
        else:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="User should be a superuser",
                headers={"WWW-Authenticate": "Bearer"},
            )
    except ValidationError as e:
        errors_list = json.loads(e.json())
        for item in errors_list:
            errors.append(item.get("loc")[0] + ": " + item.get("msg"))
        return templates.TemplateResponse(
            "auth/register.html", {"request": request, "errors": errors}
        )

解决方案

一、普通用户访问时自动携带Authorization头

当前登录后Token存在httponly Cookie中,但浏览器默认不会自动将Cookie里的Token放入Authorization头,可通过两种方式解决:

  1. 修改认证依赖,支持从Cookie提取Token
    调整get_current_active_user的实现,让它同时支持从Cookie和Authorization头获取Token:
def get_current_active_user(
    access_token: Annotated[Union[str, None], Cookie()] = None,
    token: Annotated[str, Depends(oauth2_scheme)] = None
):
    # 优先读取Cookie中的Token
    if access_token:
        # 移除Bearer前缀(如果存在)
        token = access_token.split(" ")[1] if access_token.startswith("Bearer ") else access_token
    # 原有Token解析逻辑
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise HTTPException(status_code=401, detail="Could not validate credentials")
        token_data = TokenData(username=username)
    except JWTError:
        raise HTTPException(status_code=401, detail="Could not validate credentials")
    # 获取并验证用户状态
    user = get_user(user_db, username=token_data.username)
    if user is None:
        raise HTTPException(status_code=404, detail="User not found")
    if not user.active:
        raise HTTPException(status_code=400, detail="Inactive user")
    return user
  1. 前端请求拦截自动添加请求头
    如果前端用JS发起请求(如axios、fetch),可通过拦截器自动从Cookie取Token并添加到请求头:
// 从Cookie提取Token
function getCookie(name) {
    let value = "; " + document.cookie;
    let parts = value.split("; " + name + "=");
    if (parts.length === 2) return parts.pop().split(";").shift();
}

// Axios请求拦截器示例
axios.interceptors.request.use(config => {
    const token = getCookie('access_token');
    if (token) {
        config.headers.Authorization = token;
    }
    return config;
});

二、配置Swagger UI让Authorize按钮自动携带Token

FastAPI默认集成Swagger UI,按以下步骤配置即可让按钮生效:

  1. 定义OAuth2安全方案与API元信息
from fastapi import FastAPI
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel

# 定义Token响应模型
class Token(BaseModel):
    access_token: str
    token_type: str

# 配置OAuth2认证
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")

# 初始化FastAPI时配置Swagger认证参数
app = FastAPI(
    title="你的API名称",
    version="1.0.0",
    swagger_ui_init_oauth={
        "clientId": "api-client",  # 可自定义或留空
        "appName": "你的API",
        "usePkceWithAuthorizationCodeGrant": True
    }
)
  1. 修改登录端点返回标准OAuth2响应
    让/login接口返回符合规范的Token格式:
@router.post("/login", response_model=Token)
def login(
    request: Request,
    username: str = Form(...),
    password: str = Form(...),

):
    errors = []
    user_db = pd.read_excel('users.xlsx')
    user = authenticate_user(user_db=user_db, username=username, password=password)

    access_token = create_access_token(data={"sub": username})
    
    # 设置Cookie并返回标准Token响应
    response = JSONResponse(content={"access_token": access_token, "token_type": "bearer"})
    response.set_cookie(
        key="access_token", value=f"Bearer {access_token}", httponly=True
    )
    return response
  1. 使用Authorize按钮
    启动API后访问/docs路径,点击“Authorize”按钮,输入用户名密码(或直接粘贴Token选择Bearer类型),确认后所有接口请求都会自动带上Authorization: Bearer <token>头。

内容的提问来源于stack exchange,提问作者Juan C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 21:30:25