如何在nuxt项目中使用cookie-universal-nuxt进行状态持久化和token校验?
·
在Nuxt的SSR(服务端渲染)模式下,服务器端没有localStorage。因此,更通用且安全的方案是使用Cookie来存储Token,因为Cookie在客户端和服务端都能访问,且更适合SSR场景。
cookie-universal-nuxt是Nuxt生态中处理Cookie的优秀工具,它提供了统一的API在客户端和服务端操作Cookie,非常适合实现状态持久化和Token管理。下面是基于该工具的完整方案:
一、安装与配置 cookie-universal-nuxt
1. 安装依赖
npm install cookie-universal-nuxt --save
# 或
yarn add cookie-universal-nuxt
2. 在 nuxt.config.js 中配置
export default {
modules: [
'cookie-universal-nuxt' // 注册模块
],
// 可选配置(默认即可)
cookie: {
parseJSON: true // 自动解析JSON格式的cookie值
}
}
配置后,可通过 this.$cookies(组件中)或 context.app.$cookies(服务端上下文,如asyncData、中间件)访问Cookie工具。
二、实现状态持久化与Token管理
1. Vuex中集成Cookie操作
在 store/user.js 中,通过Cookie实现Token的持久化存储:
// store/user.js
export const state = () => ({
token: null,
info: null
})
export const mutations = {
setUser(state, { token, info }) {
state.token = token
state.info = info
},
clearUser(state) {
state.token = null
state.info = null
}
}
export const actions = {
// 初始化:从Cookie加载状态(在Nuxt初始化时调用)
init({ commit, rootState }) {
// rootState.$cookies 是cookie-universal-nuxt提供的工具
const token = rootState.$cookies.get('token')
const userInfo = rootState.$cookies.get('userInfo')
if (token && userInfo) {
commit('setUser', { token, info: userInfo })
}
},
// 登录:存储Token到Vuex和Cookie
async login({ commit, rootState }, { username, password }) {
try {
const res = await this.$axios.post('/api/login', { username, password })
const { token, userInfo } = res.data
// 存储到Vuex
commit('setUser', { token, info: userInfo })
// 存储到Cookie(设置过期时间,如7天)
rootState.$cookies.set('token', token, {
maxAge: 60 * 60 * 24 * 7, // 7天有效期
path: '/', // 全站可访问
sameSite: 'lax' // 防止CSRF
})
rootState.$cookies.set('userInfo', userInfo, {
maxAge: 60 * 60 * 24 * 7,
path: '/'
})
return true
} catch (error) {
console.error('登录失败', error)
return false
}
},
// 退出登录:清除Vuex和Cookie
logout({ commit, rootState }) {
commit('clearUser')
rootState.$cookies.remove('token')
rootState.$cookies.remove('userInfo')
}
}
2. 在Nuxt初始化时加载状态
为了确保页面刷新后状态能从Cookie恢复,需在Nuxt初始化时调用init方法。
创建插件 plugins/init-store.js:
export default async ({ store }) => {
// 初始化时从Cookie加载用户状态
await store.dispatch('user/init')
}
在 nuxt.config.js 中注册:
export default {
plugins: [
'~/plugins/init-store.js', // 初始化状态
'~/plugins/axios-interceptor.js' // 后面会讲到的Axios拦截器
]
}
三、Token校验与权限控制
1. Axios拦截器(兼容SSR)
修改之前的Axios拦截器,从Vuex获取Token(而非直接读Cookie),确保客户端和服务端一致:
// plugins/axios-interceptor.js
export default function ({ $axios, store, redirect, route }) {
// 请求拦截器:添加Token
$axios.interceptors.request.use(config => {
const token = store.state.user.token
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
// 响应拦截器:处理Token过期
$axios.interceptors.response.use(
response => response,
error => {
const { response } = error
if (response && response.status === 401) {
// 清除状态和Cookie
store.dispatch('user/logout')
// 客户端环境下跳转登录页
if (process.client) {
redirect(`/login?redirect=${route.path}`)
}
}
return Promise.reject(error)
}
)
}
2. 中间件控制路由权限
修改中间件 middleware/auth.js,兼容服务端和客户端:
export default async function ({ store, redirect, route }) {
// 检查是否已登录
const isLoggedIn = !!store.state.user.token
// 未登录且访问需授权页面:跳登录页
if (!isLoggedIn && route.path !== '/login') {
return redirect(`/login?redirect=${route.path}`)
}
// 已登录访问登录页:跳首页
if (isLoggedIn && route.path === '/login') {
return redirect('/')
}
}
四、登录页实现(同上一方案,无需修改)
<!-- pages/login.vue -->
<template>
<div>
<input v-model="username" placeholder="用户名" />
<input v-model="password" type="password" placeholder="密码" />
<button @click="handleLogin">登录</button>
</div>
</template>
<script>
export default {
data() {
return {
username: '',
password: ''
}
},
methods: {
async handleLogin() {
const success = await this.$store.dispatch('user/login', {
username: this.username,
password: this.password
})
if (success) {
const redirectPath = this.$route.query.redirect || '/'
this.$router.push(redirectPath)
}
}
}
}
</script>
五、方案优势与注意事项
优势:
- SSR兼容:Cookie在客户端和服务端均可访问,避免
localStorage在服务端报错的问题。 - 安全性:通过
httpOnly和sameSite等属性可增强Cookie安全性(需后端配合设置)。 - 统一API:
cookie-universal-nuxt提供了一致的API,无需区分客户端/服务端环境。 - 自动过期:可设置Cookie过期时间,实现Token自动失效。
注意事项:
- Cookie大小限制:Cookie有4KB大小限制,不宜存储过大的用户信息(建议只存Token,用户信息通过Token在服务端获取)。
- 敏感信息保护:
- 重要场景下,后端应将Token设置为
httpOnly: true(客户端JS无法读取,防XSS)。 - 配合
secure: true(仅HTTPS传输)和sameSite: 'strict'(防CSRF)增强安全性。
- 重要场景下,后端应将Token设置为
- 服务端获取Cookie:在
asyncData或fetch中,通过context.app.$cookies访问Cookie,而非this.$cookies。
通过cookie-universal-nuxt实现的方案,完美解决了SSR环境下的状态持久化问题,是Nuxt项目中管理Token的推荐方案,兼顾了兼容性和安全性。
更多推荐


所有评论(0)