【问题标题】:FastAPI: Deleting cookies after logout not workingFastAPI:注销后删除cookie不起作用
【发布时间】:2021-07-09 16:04:44
【问题描述】:

我尝试使用 FastAPI 实现基于 OAuth2 Cookie 的身份验证。 在调用/auth/token端点时,它完美地设置了一个HttpOnly cookie,如下所示:

@router.post("/auth/token", response_model=Token)
async def get_token(response: Response, form_data: OAuth2PasswordRequestForm = Depends()):
    user = await authenticate_user(form_data.username, form_data.password)
    if not user:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect username or password")
    access_token_expires = timedelta(minutes=Config.ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.email_id}, expires_delta=access_token_expires
    )
    response.set_cookie(key="access_token", value=access_token, httponly=True)
    return {"access_token": access_token, "token_type": "bearer"}

同样,它应该在调用/logout 端点后立即删除该cookie,如下所示:

@router.get("/logout")
async def logout(request: Request, response: Response, current_user: User = Depends(get_current_active_user)):
    # Also tried following two comment lines
    # response.set_cookie(key="access_token", value="", max_age=1)
    # response.delete_cookie("access_token", domain="localhost")
    response.delete_cookie("access_token")
    return templates.TemplateResponse("login.html", {"request": request, "title": "Login", "current_user": AnonymousUser()})

问题: 调用/logout 端点后,它应该删除它所做的cookie,但是当我再次单击/login 时,它能够检索具有相同身份验证令牌的相同cookie,即浏览器发送相同的 cookie 以及请求中的身份验证令牌。

这是删除cookies后响应的调试状态。它已经从响应对象中删除了 cookie,这很好:

这是我尝试登录AFTER LOGOUT时请求的调试状态。它仍然能够从浏览器中检索该 cookie:

有关如何正确删除 cookie 以便在注销后无法再次找到它的任何帮助?

【问题讨论】:

  • 嗨@AKA,作为此答案 (stackoverflow.com/a/20320610/9058468) 中建议的最佳实践,您可以使用过期值设置 cookie
  • @Santiago 是的,但在注销时必须立即删除它。注销后,理想情况下它必须要求凭据再次登录,但在这里它只是不要求,因为它能够从请求对象中检索它。
  • 我认为问题出在注销后重定向时。当您重定向时,任何自定义标头也会发生这种情况。尝试返回一个空字符串,看看它是否有效。另外,看看this answer
  • @Santiago 最终通过对响应进行一些更改来解决它。感谢您为我指明方向。
  • 很高兴为您提供帮助。你应该接受你的答案

标签: python-3.x cookies oauth-2.0 fastapi


【解决方案1】:

问题在于响应 /logout 端点正在返回。

如下图,response.delete_cookies(key="access_token")这行可以成功删除cookie

在返回时创建 TemplateResponse 对象时,它会创建一个新的响应,从请求中复制相同的 cookie,并隐藏我们所做的更改(删除 cookie)。所以在logout()函数中交换最后两行就解决了问题:

@router.get("/logout")
async def logout(request: Request, response: Response, current_user: User = Depends(get_current_active_user)):
    # Also tried following two comment lines
    # response.set_cookie(key="access_token", value="", max_age=1)
    # response.delete_cookie("access_token", domain="localhost")
    response = templates.TemplateResponse("login.html", {"request": request, "title": "Login", "current_user": AnonymousUser()})
    response.delete_cookie("access_token")
    return response

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-01
    • 2019-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    • 2016-04-27
    • 2016-06-03
    相关资源
    最近更新 更多