在从本地存储恢复 Vuex Store 之前执行的中间件
Posted
技术标签:
【中文标题】在从本地存储恢复 Vuex Store 之前执行的中间件【英文标题】:Middleware executing before Vuex Store restore from localstorage 【发布时间】:2019-07-14 08:21:45 【问题描述】:在 nuxtjs 项目中,我创建了一个身份验证中间件来保护页面。 并使用 vuex-persistedstate(也尝试过 vuex-persist 和 nuxt-vuex-persist)来持久化 vuex 存储。
从一个页面导航到另一个页面时一切正常,但是当我刷新页面或直接登陆到受保护的路线时,它会将我重定向到登录页面。
本地存储插件
import createPersistedState from 'vuex-persistedstate'
export default ( store ) =>
createPersistedState(
key: 'store-key'
)(store)
身份验证中间件
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()
【问题讨论】:
也遇到过这种情况。你有进步吗? @SeanRussell 我未能解决问题,但通过创建重定向页面找到了绕过此问题的方法。在我的案例中,存储数据位于客户端的本地存储中。因此,每当我们执行刷新时,服务器都会尝试在服务器上找到存储数据,这就是它。所以我创建了一个重定向页面。并相应地更改上述功能。发送邮件至 yashdeep.rajput019@gmail.com 获取代码。 @auedbaki 你能在这里发布解决方案吗?谢谢 【参考方案1】:我通过使用这个插件 vuex-persistedstate 而不是 vuex-persist 插件解决了这个问题。似乎 vuex-persist 中存在一些错误(或可能是设计架构)导致它。
【讨论】:
这无法通过客户端解决方案来解决。这是因为服务器端没有 Vuex Store 值。这些库是不可能的。您将体验到使用在服务器端运行的 asyncData 函数。 哦。这可能是非常真实的。但是我在客户端使用 vuex-persist 遇到了这个问题。在搜索谷歌时,这个页面是我能找到的最好的结果,所以也许其他人在使用 vuex-persist 时遇到问题(在插件中解决问题之前)可以看到我的评论,这会有所帮助。此外,问题中的服务器上没有任何内容,所以我不知道。【参考方案2】:使用当前的方法,我们总是会失败。
实际问题是 Vuex 存储永远无法与服务器端 Vuex 存储同步。
事实上,我们只需要数据字符串与客户端和服务器(令牌)同步。
我们可以通过 Cookies 实现这种同步。因为 cookie 会自动传递给来自浏览器的每个请求。所以我们不需要设置任何请求。您可以直接从浏览器地址栏或导航中点击 URL。
我建议使用模块 'cookie-universal-nuxt' 来设置和删除 cookie。
登录后设置cookie
this.$cookies.set('token', 'Bearer '+response.tokens.access_token, path: '/', maxAge: 60 * 60 * 12 )
用于在注销时删除 cookie
this.$cookies.remove('token')
请阅读文档以获得更好的理解。
我也在使用@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)
)
,
下面是我的 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()
我已经为不同的令牌来源编写了不同的条件,就像在代码中一样。在服务器进程上,我从 cookie 获取令牌,在客户端获取令牌存储。 (这里我们也可以从cookies中获取)
在此之后,由于布局中的存储数据绑定,您可能会遇到一些水合问题。为解决此问题,请使用 <no-s-s-r></no-s-s-r>
包装此类模板代码。
【讨论】:
以上是关于在从本地存储恢复 Vuex Store 之前执行的中间件的主要内容,如果未能解决你的问题,请参考以下文章