问题根源分析
- 客户端请求正常:点击按钮时,浏览器能读取
localStorage
的 Token 并添加到请求头。 - SSR 请求异常:刷新页面时,服务端渲染期间发起的请求无法访问
localStorage
(仅浏览器环境存在),导致 Token 缺失。
解决方案:改用 Cookie 存储 Token
Cookie 在 SSR 中可被服务端通过请求头读取,同时在浏览器端也能自动携带。需调整前后端逻辑:
1. 前端修改:将 Token 存储到 Cookie
使用 Nuxt3 的 useCookie
在登录成功后存储 Token:
typescript
// 登录成功后的代码
const token = useCookie('token') // 使用 useCookie 创建响应式 Cookie
token.value = response.data.token // 将 Token 存入 Cookie
关键点:
useCookie
会在服务端渲染时自动读取请求头中的 Cookie。- 自动处理浏览器和服务器环境,无需手动操作
document.cookie
。
2. 前端修改:请求时自动携带 Cookie 中的 Token
在发起请求时,从 Cookie 读取 Token 并添加到请求头。推荐在 Nuxt3 的 HTTP 客户端 拦截器中实现:
typescript
// ~/composables/useApi.ts
export const useApi = () => {
const { $fetch } = useNuxtApp()
const token = useCookie('token')
// 自定义请求方法
const apiFetch = (url: string, options: any = {}) => {
const headers = {
...options.headers,
Authorization: token.value ? `Bearer ${token.value}` : '',
}
return $fetch(url, {
...options,
headers,
})
}
return {
apiFetch,
}
}
使用示例(在组件或页面中):
typescript
const { apiFetch } = useApi()
// 发起请求
apiFetch('/api/data', { method: 'GET' })
3. 后端修改(Koa2):从 Cookie 解析 Token
确保后端中间件能正确读取 Cookie 中的 Token:
javascript
// Koa 中间件
app.use(async (ctx, next) => {
const token = ctx.cookies.get('token') || ''
// 验证 Token(示例使用 jsonwebtoken)
if (token) {
try {
const decoded = jwt.verify(token, 'your-secret-key')
ctx.state.user = decoded // 将用户信息挂载到上下文
} catch (err) {
ctx.cookies.set('token', null) // 清除无效 Token
}
}
await next()
})
关键点:
- 使用
koa-cookie
或koa-bodyparser
中间件确保正确解析 Cookie。 - 验证 Token 后处理用户状态(如挂载到
ctx.state
)。
4. 安全配置(可选但强烈建议)
- Cookie 属性加固:
typescript
const token = useCookie('token', {
httpOnly: true, // 防止 XSS 读取
secure: true, // 仅 HTTPS 传输
sameSite: 'strict',// 防止 CSRF
maxAge: 86400 // 有效期(秒)
})
- CORS 配置(若跨域):
javascript
// Koa 中间件
ctx.set('Access-Control-Allow-Origin', 'https://your-domain.com')
ctx.set('Access-Control-Allow-Credentials', 'true')
验证流程
- 用户登录 → Token 存入 Cookie。
- 页面刷新 → SSR 服务端读取 Cookie 中的 Token → 发起 API 请求时携带 Token。
- 后端验证 Token → 返回数据。
可能遇到的问题
- Cookie 未生效:检查域名、路径和安全性设置,确保前后端同域或跨域配置正确。
- HttpOnly 与前端读取冲突:如果前端需要读取 Token,需移除
httpOnly
,但需加强 XSS 防御。 - 客户端跳转后 Cookie 丢失:确保登录后 Cookie 成功写入,可通过浏览器开发者工具查看。
通过以上步骤,SSR 请求将能正确携带 Token,解决刷新页面时的认证问题。