Cookie 助手
Cookie 助手提供简洁的接口来管理 Cookie,便于开发者设置、解析与删除 Cookie。
导入
ts
import { Hono } from 'hono'
import {
deleteCookie,
getCookie,
getSignedCookie,
setCookie,
setSignedCookie,
generateCookie,
generateSignedCookie,
} from 'hono/cookie'用法
普通 Cookie
ts
app.get('/cookie', (c) => {
setCookie(c, 'cookie_name', 'cookie_value')
const yummyCookie = getCookie(c, 'cookie_name')
deleteCookie(c, 'cookie_name')
const allCookies = getCookie(c)
// ...
})签名 Cookie
注意:由于 WebCrypto API 的异步特性(用于生成 HMAC SHA-256 签名),签名 Cookie 的设置与读取都返回 Promise。
ts
app.get('/signed-cookie', async (c) => {
const secret = 'secret' // 确保密钥长度足够安全
await setSignedCookie(c, 'cookie_name0', 'cookie_value', secret)
const fortuneCookie = await getSignedCookie(
c,
secret,
'cookie_name0'
)
deleteCookie(c, 'cookie_name0')
// 如果签名被篡改或无效,`getSignedCookie` 会返回 `false`
const allSignedCookies = await getSignedCookie(c, secret)
// ...
})生成 Cookie
generateCookie 与 generateSignedCookie 函数允许你直接生成 Cookie 字符串,而无需在响应头中设置。
generateCookie
ts
// 基础用法
const cookie = generateCookie('delicious_cookie', 'macha')
// 返回:'delicious_cookie=macha; Path=/'
// 带配置项的 Cookie
const cookie = generateCookie('delicious_cookie', 'macha', {
path: '/',
secure: true,
httpOnly: true,
domain: 'example.com',
})generateSignedCookie
ts
// 基础的签名 Cookie 生成
const signedCookie = await generateSignedCookie(
'delicious_cookie',
'macha',
'secret chocolate chips'
)
// 带配置项的签名 Cookie
const signedCookie = await generateSignedCookie(
'delicious_cookie',
'macha',
'secret chocolate chips',
{
path: '/',
secure: true,
httpOnly: true,
}
)注意:与 setCookie 和 setSignedCookie 不同,这两个函数只会返回生成好的 Cookie 字符串,如有需要需自行设置到响应头中。
配置项
setCookie 与 setSignedCookie
- domain:
string - expires:
Date - httpOnly:
boolean - maxAge:
number - path:
string - secure:
boolean - sameSite:
'Strict'|'Lax'|'None' - priority:
'Low' | 'Medium' | 'High' - prefix:
secure|'host' - partitioned:
boolean
示例:
ts
// 普通 Cookie
setCookie(c, 'great_cookie', 'banana', {
path: '/',
secure: true,
domain: 'example.com',
httpOnly: true,
maxAge: 1000,
expires: new Date(Date.UTC(2000, 11, 24, 10, 30, 59, 900)),
sameSite: 'Strict',
})
// 签名 Cookie
await setSignedCookie(
c,
'fortune_cookie',
'lots-of-money',
'secret ingredient',
{
path: '/',
secure: true,
domain: 'example.com',
httpOnly: true,
maxAge: 1000,
expires: new Date(Date.UTC(2000, 11, 24, 10, 30, 59, 900)),
sameSite: 'Strict',
}
)deleteCookie
- path:
string - secure:
boolean - domain:
string
示例:
ts
deleteCookie(c, 'banana', {
path: '/',
secure: true,
domain: 'example.com',
})deleteCookie 会返回被删除的值:
ts
const deletedCookie = deleteCookie(c, 'delicious_cookie')__Secure- 与 __Host- 前缀
Cookie 助手支持在 Cookie 名称中使用 __Secure- 与 __Host- 前缀。
如果想确认 Cookie 名称是否携带前缀,可以通过 prefix 选项指定期望的前缀。
ts
const securePrefixCookie = getCookie(c, 'yummy_cookie', 'secure')
const hostPrefixCookie = getCookie(c, 'yummy_cookie', 'host')
const securePrefixSignedCookie = await getSignedCookie(
c,
secret,
'fortune_cookie',
'secure'
)
const hostPrefixSignedCookie = await getSignedCookie(
c,
secret,
'fortune_cookie',
'host'
)同样地,如果在设置 Cookie 时需要指定前缀,可以为 prefix 选项赋值。
ts
setCookie(c, 'delicious_cookie', 'macha', {
prefix: 'secure', // 或 `host`
})
await setSignedCookie(
c,
'delicious_cookie',
'macha',
'secret choco chips',
{
prefix: 'secure', // 或 `host`
}
)遵循最佳实践
最新的 Cookie RFC(又称 cookie-bis)与 CHIPS 规范提出了一系列 Cookie 设置最佳实践,开发者应遵循这些规则。
- RFC6265bis-13
Max-Age/Expires限制__Host-/__Secure-前缀限制
- CHIPS-01
Partitioned限制
Hono 遵循上述最佳实践。当出现以下情况时,Cookie 助手会抛出 Error:
- Cookie 名称以
__Secure-开头,但未设置secure选项。 - Cookie 名称以
__Host-开头,但未设置secure选项。 - Cookie 名称以
__Host-开头,但path不是/。 - Cookie 名称以
__Host-开头,但设置了domain。 maxAge选项的值大于 400 天。expires选项的值晚于当前时间 400 天。