FastAPI使用APIKeyCookie时未触发401却返回404及依赖未执行问题
我有一个POST路由/publish,依赖get_current_user,该依赖又依赖fastapi.security.APIKeyCookie。认证正常时运行正常,但不带cookie用curl请求时返回404 Not Found,且get_current_user未被调用。为何缺少cookie时不返回401?我尝试设置APIKeyCookie的auto_error=False,但get_current_user仍未执行。这是预期行为吗?
示例代码
auth.py
import fastapi import pydantic import typing as t import logging logger = logging.getLogger(__name__) cookie_scheme = fastapi.security.APIKeyCookie(name="access_token_cookie", auto_error=False) JWT_ALGORITHM = "HS256" class UserAuthorization(pydantic.BaseModel): username: str groups: list[str] async def get_current_user( token: t.Annotated[str | None, fastapi.Depends(cookie_scheme)], ) -> UserAuthorization: logger.info("inside get_current_user()") # 这段代码从未执行
main.py
import fastapi import auth app = fastapi.FastAPI() @app.post( "/publish", status_code=fastapi.status.HTTP_201_CREATED, dependencies=[fastapi.Depends(auth.get_current_user)], ) async def publish(): return {"message": "Published successfully"}
测试情况
不带cookie请求
$ curl -X POST myserver/publish <!doctype html> <html lang=en> <title>404 Not Found</title> <h1>Not Found</h1> <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
带无效cookie值请求
$ curl -X POST myserver/publish -b "access_token_cookie=someWrongValue" <!doctype html> <html lang=en> <title>Redirecting...</title> <h1>Redirecting...</h1> <p>You should be redirected automatically to the target URL: <a href="myserver/publish">myserver/publish</a>. If not, click the link.
核心原因:路由匹配与自动重定向冲突
FastAPI默认开启自动重定向——当请求路径不带末尾斜杠(如/publish),但路由定义带斜杠(或反之)时,框架会返回307重定向到标准路径。如果请求未携带cookie,重定向过程中可能出现路径匹配失效,导致最终返回404;此时路由未被正确匹配,依赖项get_current_user自然不会执行。
另外,APIKeyCookie默认auto_error=True,无cookie时会直接抛出401,但前提是路由被正确匹配。若重定向导致路径无法匹配,这个异常也不会触发。
解决步骤
统一路径格式
确保路由定义和请求路径的末尾斜杠完全一致:要么路由写/publish/,请求也用myserver/publish/;要么都不带斜杠。关闭自动重定向
初始化FastAPI时禁用自动重定向功能,避免路径匹配混乱:app = fastapi.FastAPI(redirect_slashes=False)完善认证逻辑
即使auto_error=False让cookie_scheme返回None,也要在get_current_user中主动校验token,抛出401异常:async def get_current_user( token: t.Annotated[str | None, fastapi.Depends(cookie_scheme)], ) -> UserAuthorization: logger.info("inside get_current_user()") if not token: raise fastapi.HTTPException( status_code=fastapi.status.HTTP_401_UNAUTHORIZED, detail="未提供认证Cookie" ) # 此处补充JWT解析、用户信息校验逻辑 return UserAuthorization(username="test", groups=["admin"])
验证结果
修复路径匹配问题后,不带cookie请求时get_current_user会被执行,主动抛出401异常,返回正确的未授权响应,而非404。
内容的提问来源于stack exchange,提问作者Amit

