aue*_*aki 5 persistence local-storage vue.js vuex nuxt.js
在 nuxtjs 项目中,我创建了一个 auth 中间件来保护页面。并使用 vuex-persistedstate(也尝试过 vuex-persist 和 nuxt-vuex-persist)来持久化 vuex 存储。
在页面之间导航时一切正常,但是当我刷新页面或直接登陆受保护的路由时,它会将我重定向到登录页面。
本地存储插件
import createPersistedState from 'vuex-persistedstate'
export default ({ store }) => {
createPersistedState({
key: 'store-key'
})(store)
}
Run Code Online (Sandbox Code Playgroud)
认证中间件
export default function ({ req, store, redirect, route }) {
const userIsLoggedIn = !!store.state.auth.user
if (!userIsLoggedIn) {
return redirect(`/auth/login?redirect=${route.fullPath}`)
}
return Promise.resolve()
}
Run Code Online (Sandbox Code Playgroud)
按照当前的方法,我们总是会失败。
实际问题是 Vuex 存储永远无法与服务器端 Vuex 存储同步。
事实上,我们只需要数据字符串与客户端和服务器(令牌)同步。
我们可以通过Cookies来实现这种同步。因为 cookie 会自动传递给来自浏览器的每个请求。所以我们不需要设置任何请求。您只需从浏览器地址栏或通过导航点击 URL。
我建议使用模块“cookie-universal-nuxt”来设置和删除 cookie。
用于登录后设置cookie
this.$cookies.set('token', 'Bearer '+response.tokens.access_token, { path: '/', maxAge: 60 * 60 * 12 })
Run Code Online (Sandbox Code Playgroud)
用于在注销时删除 cookie
this.$cookies.remove('token')
Run Code Online (Sandbox Code Playgroud)
请仔细阅读文档以更好地理解。
我还使用@nuxt/http模块进行 api 请求。
现在 nuxt 在 vuex 存储索引文件中有一个名为 nuxtServerInit() 的函数。您应该使用它从请求中检索令牌并将其设置为 http 模块标头。
async nuxtServerInit ({dispatch, commit}, {app, $http, req}) {
return new Promise((resolve, reject) => {
let token = app.$cookies.get('token')
if(!!token) {
$http.setToken(token, 'Bearer')
}
return resolve(true)
})
},
Run Code Online (Sandbox Code Playgroud)
下面是我的 nuxt 页面级中间件
export default function ({app, req, store, redirect, route, context }) {
if(process.server) {
let token = app.$cookies.get('token')
if(!token) {
return redirect({path: '/auth/login', query: {redirect: route.fullPath, message: 'Token Not Provided'}})
} else if(!isTokenValid(token.slice(7))) { // slice(7) used to trim Bearer(space)
return redirect({path: '/auth/login', query: {redirect: route.fullPath, message: 'Token Expired'}})
}
return Promise.resolve()
}
else {
const userIsLoggedIn = !!store.state.auth.user
if (!userIsLoggedIn) {
return redirect({path: '/auth/login', query: {redirect: route.fullPath}})
// return redirect(`/auth/login?redirect=${route.fullPath}`)
} else if (!isTokenValid(store.state.auth.tokens.access_token)) {
return redirect({path: '/auth/login', query: {redirect: route.fullPath, message: 'Token Expired'}})
// return redirect(`/auth/login?redirect=${route.fullPath}&message=Token Expired`)
} else if (isTokenValid(store.state.auth.tokens.refresh_token)) {
return redirect(`/auth/refresh`)
} else if (store.state.auth.user.role !== 'admin')
return redirect(`/403?message=Not having sufficient permission`)
return Promise.resolve()
}
}
Run Code Online (Sandbox Code Playgroud)
我已经为不同的令牌源编写了不同的条件,如代码中所示。在服务器进程上,我从 cookie 获取令牌,在客户端获取令牌存储。(这里我们也可以从cookie中获取)
之后,由于布局中的存储数据绑定,您可能会遇到一些水合问题。为了解决这个问题,请使用<no-ssr></no-ssr>此类模板代码的包装。
| 归档时间: |
|
| 查看次数: |
1211 次 |
| 最近记录: |