从本地存储还原 Vuex Store 前执行的中间件

5
在Nuxt.js项目中,我创建了一个身份验证中间件来保护页面,并使用vuex-persistedstate(也尝试过vuex-persist和nuxt-vuex-persist)来持久化vuex store。 当从一个页面导航到另一个页面时,一切都正常,但是当我刷新页面或直接访问受保护的路由时,它会将我重定向到登录页面。 localStorage插件。
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()
}

也遇到了这个问题。你有取得任何进展吗? - Sean Russell
2
@SeanRussell,我在解决问题时失败了,但是通过创建重定向页面找到了一个绕过方法。在我的情况下,存储数据位于客户端的本地存储中。因此,每当我们执行刷新操作时,服务器会尝试在服务器上查找存储数据,这就是它的原因。所以我创建了一个重定向页面,并相应地更改了上面的函数。请发送电子邮件至yashdeep.rajput019@gmail.com获取代码。 - Yashdeep Raj
@auedbaki,您能在这里发布解决方案吗?谢谢。 - Abbas
2个回答

1

以目前的方法,我们将永远失败。

实际问题是Vuex Store无法与服务器端的Vuex Store同步。

事实上,我们只需要数据字符串与客户端和服务器同步(令牌)。

我们可以通过Cookies实现此同步。因为Cookies会自动传递给浏览器的每个请求。所以我们不需要设置任何请求。您只需从浏览器地址栏或导航中访问URL即可。

我建议使用模块'cookie-universal-nuxt'来设置和删除Cookies。

用于登录后设置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 中获取令牌,在客户端获取令牌存储。(这里我们也可以从 cookie 中获取)

之后,由于布局中存储数据绑定的原因,您可能会遇到一些水合问题。为了解决这个问题,请使用 <no-ssr></no-ssr> 包装此类模板代码。


1
我很惊讶这个主题没有更多的文档或评论。在服务器端无法访问浏览器本地存储,也就是说,存储访问将始终为未定义。我的身份验证中间件也使用了cookie。当然,我是在nuxt的ssr模式下而不是spa模式下进行讨论的。 - pregmatch

0

我通过使用这个插件vuex-persistedstate解决了这个问题,而不是使用vuex-persist插件。看起来在vuex-persist中存在一些错误(或可能是设计架构)导致了这个问题。


1
这个问题不能通过客户端解决。这是由于在服务器端缺少Vuex Store值造成的,而使用这些库是不可能的。当使用在服务器端运行的asyncData函数时,您会遇到这个问题。 - Yashdeep Raj
哦,那可能非常真实。但我在客户端使用 vuex-persist 时遇到了这个问题。在谷歌上搜索后,这个页面是我能找到的最好的结果,因此也许其他在使用 vuex-persist 时遇到问题(在插件中解决之前)的人可以看到我的评论并且从中获得帮助。此外,问题中没有涉及服务器,所以我不知道那方面的情况。 - Elijah Kolawole

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,