You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在设置Cookie max-age时本地化Date.now()以修正过期时间?

问题:Cookie的max-age因夏令时导致过期时间计算错误?

我在服务端设置Cookie时,希望把max-age设为1800秒。按我的理解,浏览器会从Date.now()开始计算,1800秒后过期。但现在遇到个问题:浏览器里打印Date.now()的时候,时间没本地化——当前处于夏令时,实际时间是下午3:19,但显示的是下午2:19,结果Cookie的过期时间直接被设成了30分钟前。

我的Cookie设置函数是这样的:

setTokenCookie(token) {
  this.cookies.set("refresh_token", token.refresh_token, { signed: true, httpOnly: true })
  this.cookies.set("access_token", token.access_token, { signed: true, httpOnly: true, maxAge: token.expires_in })
}

请问有没有办法让Cookie过期时间在设置前先对Date.now()做本地化处理?


解决方案

其实你误解了max-age的工作原理——它不依赖本地时间,而是以浏览器收到Cookie的那一刻为起点,计算相对的秒数,和时区、夏令时完全无关!

那为什么会出现你看到的“过期时间显示成30分钟前”的问题?大概率是你在浏览器开发者工具里查看Cookie过期时间时,浏览器把服务端返回的UTC时间自动转换成了本地时间,但max-age的计算逻辑是绝对的相对时长,根本不会因为时区偏移出问题,这只是个显示层面的错觉而已。

不过如果你还是想彻底解决这个显示上的混淆,可以改用expires属性来设置绝对过期时间,手动基于本地时间计算后转成UTC格式:

setTokenCookie(token) {
  this.cookies.set("refresh_token", token.refresh_token, { signed: true, httpOnly: true })
  
  // 计算绝对过期时间:当前本地时间加上expires_in秒
  const expiryDate = new Date();
  expiryDate.setSeconds(expiryDate.getSeconds() + token.expires_in);
  
  this.cookies.set("access_token", token.access_token, { 
    signed: true, 
    httpOnly: true, 
    expires: expiryDate // 用expires替代maxAge
  })
}

这里有几个关键点要注意:

  • new Date()会自动获取当前的本地时间,包括夏令时的时区偏移
  • 当你把这个Date对象传给expires时,绝大多数后端框架(比如Express的cookie-parser)会自动把它转换成符合Cookie标准的UTC格式字符串
  • 这样浏览器收到的就是一个明确的UTC过期时间,转换成本地时间后就会和你实际的本地时间完全匹配,不会再出现“过期时间在过去”的奇怪显示

最后再捋一遍:

  • 如果用max-age,完全不需要折腾时区,它的逻辑是相对时长,本身没有错误,你看到的只是UTC转本地的视觉问题
  • 如果想彻底消除显示上的困惑,就改用expires属性,基于本地时间计算过期点即可

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

火山引擎 最新活动