ame*_*ian 2 cookies python-3.x cookie-httponly fastapi uvicorn
我第一次使用 HTTpOnly Cookie 实现登录身份验证。就我而言,当用户使用 fastapi 和 uvicorn 在Python 服务中调用登录方法时创建 cookie 。
我已经阅读了MDN文档来实现 expires 属性,因此,浏览器会在时间到期时删除此 cookie。
我已经使用 http.cookies 和Morsel在 Python 中实现了 Cookie,以应用HttpOnly属性,如下所示:
from http import cookies
from fastapi import FastAPI, Response, Cookie, Request
from fastapi.responses import HTMLResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
mytoken = 'blablabla'
def getUtcDate():
sessionDate = datetime.now()
sessionDate += timedelta(minutes=2)
return sessionDate.strftime('%a, %d %b %Y %H:%M:%S GMT')
@app.get('cookietest')
def getCookie(response: Response):
cookie = cookies.Morsel()
cookie['httponly'] = True
cookie['version'] = '1.0.0'
cookie['domain'] = '127.0.0.1'
cookie['path'] = '/'
cookie['expires'] = getUtcDate()
cookie['max-age'] = 120
cookie['samesite'] = 'Strict'
cookie.set("jwt", "jwt", mytoken)
response.headers.append("Set-Cookie", cookie.output())
return {'status':'ok'}
Run Code Online (Sandbox Code Playgroud)
这样做,当我调用“cookietest”端点时,Cookie 在浏览器中看起来正确,证据如下:
如图所示,cookie 在 Expires / Max-Age 中有一个过期日期时间:“Wed, 12 Oct 2022 11:24:58 GMT”,登录后 2 分钟(如果用户在 14:05 登录: 00,cookie 于 14:07:00 过期)
我的问题是,当超过过期时间时,任何浏览器都不会删除 cookie,所以这让我感到困惑。如果我过了几分钟然后向另一个端点(例如http://127.0.0.1:8000/info)发出请求,则 cookie 仍然存在于 http 标头中。
问题是什么?我做错了什么?我正在阅读大量有关 cookie 存储和过期的文档,但我看不到任何有关此问题的信息。
非常感谢 问候
正如Chris所说,使用 FastApi 中的 set_cookie 方法解决了问题。
我仍然想知道为什么MSD文档指示日期格式必须是特定的格式,这不会导致浏览器删除Cookie,但指示以秒为单位的时间可以正常工作。
@app.get("/cookietest")
async def cookietest(response: Response):
response.set_cookie(
key='jwt',
value=getToken(),
max_age=120,
expires=120,
path='/',
secure=False,
httponly=True,
samesite="strict",
domain='127.0.0.1'
)
return {"Result": "Ok"}
Run Code Online (Sandbox Code Playgroud)
使用该expires标志时,日期必须完全符合您当前使用的格式以及GMT(格林威治标准时间)时区。您的 cookie 在创建后 2 分钟内不会过期的原因是您使用的是datetime.now(),它返回当前的本地日期和时间。
因此,举例来说,如果您当前的本地时区是GMT+2,时间是20:30:00(因此,GMT时间是18:30:00),创建一个过期的 cookie20:32:00 GMT实际上会告诉浏览器在 2 小时 2 分钟后删除该 cookie(从创建它的时间算起) )。Expires / Max-Age如果您查看浏览器的 DevTools 中的cookie列(例如,在 Chrome 上,转到NetworkDevTools 中的选项卡,单击请求的名称,然后单击选项卡),您会Cookies注意到Z日期时间的末尾,这意味着UTC(协调世界时)\xe2\x80\x94,即与 UTC 的零小时-分钟-秒的偏移量。您还可以检查响应标头,您可以在其中看到 cookie 的expires标志设置为20:32:00 GMT。和之间没有明显的时间差异UTCGMT(如果您想了解更多关于它们的差异,请查看这篇文章)。
因此,您可以在代码中替换.now()为:.utcnow()
from datetime import timedelta, datetime\n\ndef get_expiry():\n expiry = datetime.utcnow()\n expiry += timedelta(seconds=120)\n return expiry.strftime(\'%a, %d-%b-%Y %T GMT\')\nRun Code Online (Sandbox Code Playgroud)\n或使用time.gmtime(),传递secstime.time ()(返回以秒为单位的时间)加上所需的租约时间(以秒为单位)作为参数:
import time\n\ndef get_expiry():\n lease = 120 # seconds\n end = time.gmtime(time.time() + lease)\n return time.strftime(\'%a, %d-%b-%Y %T GMT\', end)\nRun Code Online (Sandbox Code Playgroud)\n对于上述两种方法,请使用:
\ncookie[\'expires\'] = get_expiry()\nRun Code Online (Sandbox Code Playgroud)\n您还可以使用未记录的方式直接以秒为单位传递到期时间。例如:
\ncookie[\'expires\'] = 120\nRun Code Online (Sandbox Code Playgroud)\n另一种方法expires是max-ageflag ,它指定 cookie 从当前时刻起的过期时间(以秒为单位)(与上面的方式类似)。如果设置为零或负值,则 cookie 将被立即删除。例子:
cookie[\'max-age\'] = 120\nRun Code Online (Sandbox Code Playgroud)\n如果 和expires均已max-age设置,max-age则具有优先权(请参阅 MDN 上的相关文档)。
另外,根据RFC 6265:
\n\n\n4.1.2.1. 属性
\nExpires该
\nExpires属性指示 cookie 的最长生命周期,\n表示为cookie 过期的日期和时间。在指定日期过去之前,\n用户代理不需要保留 cookie。事实上,用户代理经常由于内存压力或隐私问题而逐出 cookie。4.1.2.2. 属性
\nMax-Age该
\nMax-Age属性指示 cookie 的最长生命周期,\n表示为cookie 过期之前的秒数。用户代理不需要在指定的时间内保留 cookie。事实上,用户代理经常由于内存压力或隐私问题而逐出 cookie。Run Code Online (Sandbox Code Playgroud)\nNOTE: Some existing user agents do not support the Max-Age \nattribute. User agents that do not support the Max-Age attribute \nignore the attribute.\n如果 cookie同时
\nMax-Age具有和属性Expires,则属性Max-Age具有优先权并控制 cookie 的过期日期。如果 cookie既没有Max-Age也没有\Expiresn 属性,则用户代理将保留该 cookie 直到“当前会话结束”(由用户代理定义)。
另请注意,正如MDN 文档中有关该expires标志的内容所述:
\n\n警告:许多 Web 浏览器具有会话恢复功能,该功能将保存所有选项卡并在下次使用浏览器时恢复它们。\n会话 cookie 也将被恢复,就好像浏览器从未关闭过\n一样。
\n
另一件需要注意的事情是,自 2022 年 9 月起,Chrome 将 cookie 的有效期限制max-age为 400 天:
\n\n当使用显式属性设置 cookie 时,
\nExpires/Max-Age\n值现在将限制为未来不超过 400 天。\n以前没有限制,并且 cookie 可能会在未来几千年\n过期。
还应该注意的是,FastAPI/Starlette 提供了一种更简单的方法来在Response对象上设置 cookie,使用set_cookie方法,如本答案中所述。根据Starlette 文档:
\n\n\n
\n- \n
max_age- 一个整数,定义 cookie 的生存期(以 秒为单位) 。负整数或 的值0将立即丢弃 cookie。Optional- \n
expires-定义 cookie 过期之前的秒数的整数。Optional
FastAPI 文档中的示例:
\ncookie[\'expires\'] = get_expiry()\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
2252 次 |
| 最近记录: |