Hono 工程化实战 04:登录、Session 和 Refresh Token 设计
登录系统看起来简单。
用户输入账号密码,后端返回 token,前端存起来,之后请求带上 token。
但生产里,登录系统很容易写出安全坑:
1 | access token 有效期太长 |
Hono 不会替你规定认证模型。
这很好,因为你很自由。
但这也意味着你要自己把登录、会话、刷新、退出、权限变化设计清楚。
这篇文章讲 Hono 前后端分离项目里一套比较稳的认证设计。
技术栈快照时间:2026-06-23。Hono Cookie Helper、JWT Helper、JWT Middleware 相关 API 会更新,生产使用前以官方文档为准。
一、先区分三个概念
很多认证设计混乱,是因为把这三个东西混在一起:
1 | 用户身份 |
用户身份是:
1 | userId |
访问令牌是:
1 | access token |
会话状态是:
1 | refresh token |
生产系统里,不要只靠一个长期 JWT 解决所有问题。
长期 JWT 最大的问题是撤销困难。
二、推荐的前后端分离模型
我更推荐:
1 | access token:短期,比如 10-30 分钟 |
流程:
1 | 1. 用户登录 |
这样做的好处:
1 | access token 泄露窗口短 |
三、session 表设计
可以先从这张表开始:
1 | create table sessions ( |
注意存 token_hash,不要明文存 refresh token。
如果数据库泄露,明文 refresh token 会直接变成登录凭证。
hash 可以这样做:
1 | async function sha256(input: string) { |
四、登录接口
示例:
1 | import { Hono } from 'hono' |
这里有几个关键点:
1 | refresh token 放 HttpOnly cookie |
五、为什么 refresh token 要轮换
刷新接口不要一直复用同一个 refresh token。
更好的做法是每次刷新都轮换:
1 | 旧 refresh token 用一次就失效 |
这样即使旧 token 泄露,也会更快失效。
刷新接口:
1 | import { getCookie, setCookie } from 'hono/cookie' |
这比“refresh token 永不过期、永不变化”安全得多。
六、鉴权 middleware
API 请求带 access token:
1 | Authorization: Bearer <access-token> |
middleware:
1 | import { verify } from 'hono/jwt' |
如果你的权限经常变化,不要把所有权限都塞进 access token。
可以只放:
1 | sub |
权限在请求时查数据库或缓存。
七、退出登录要撤销 session
退出登录不应该只是前端删 token。
后端也要撤销 session:
1 | import { deleteCookie } from 'hono/cookie' |
注意 access token 可能还会在短时间内有效。
所以 access token 的有效期不要太长。
如果你必须立即失效 access token,就需要在鉴权时检查 session 是否 revoked。
这会多一次查询。
安全和性能要权衡。
八、多设备登录
有了 sessions 表,就能做多设备管理。
例如查询当前用户所有登录设备:
1 | select id, user_agent, ip, created_at, updated_at, expires_at |
用户可以手动踢掉某个设备:
1 | app.delete('/api/auth/sessions/:id', auth, async (c) => { |
这是长期 JWT 很难优雅处理的需求。
九、Cookie 和 CORS 要一起考虑
如果 refresh token 用 cookie,前后端分离时要注意 CORS。
后端 CORS:
1 | app.use('/api/*', cors({ |
前端请求 refresh:
1 | await fetch('https://api.example.com/api/auth/refresh', { |
如果 credentials 没配好,cookie 不会带上。
如果 CORS origin 写成 *,带凭证请求也会出问题。
认证系统里的 CORS 不要靠猜。
十、什么时候用纯 Cookie Session
如果你的前端和 API 在同一个主站域名下,也可以用纯 Cookie Session。
比如:
1 | app.example.com |
这时可以让所有 API 都通过 HttpOnly session cookie 认证。
优点:
1 | 前端不用管理 access token |
缺点:
1 | CSRF 要更认真处理 |
没有绝对正确。
如果是 SPA + 独立 API + 移动端共用,我更偏向 access token + refresh cookie。
如果是传统 Web 应用,纯 cookie session 很舒服。
十一、认证设计清单
上线前至少检查:
1 | access token 是否短期有效 |
登录系统不是“能登录”就完事。
它要能安全地登录、刷新、退出、撤销、追踪。
Hono 给你的认证工具足够轻。
真正决定安全性的,是你对会话生命周期的设计。