programing

로컬 스토리지에서 Vuex Store를 복원하기 전에 미들웨어 실행

yoursource 2022. 8. 14. 12:32
반응형

로컬 스토리지에서 Vuex Store를 복원하기 전에 미들웨어 실행

nuxtjs 프로젝트에서 페이지를 보호할 인증 미들웨어를 만들었습니다.vuex-displaystate(vuex-display 및 nuxt-vuex-display도 시도)를 사용하여 vuex 스토어를 유지합니다.

페이지 간을 이동할 때는 모든 것이 정상적으로 작동하지만 페이지를 새로 고치거나 보호된 경로에 직접 착지하면 로그인 페이지로 리디렉션됩니다.

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()
}

vuex-persist 플러그인 대신 이 플러그인 vuex-persistedstate를 사용하여 이 문제를 해결했습니다.vuex-persist에 버그(또는 설계 아키텍처)가 있는 것 같습니다.

Current 접근 방식으로는 항상 실패할 것입니다.

실제 문제는 Vuex Store를 서버 측 Vuex Store와 동기화할 수 없다는 것입니다.

실제로는 클라이언트 및 서버(토큰)와 동기화하는 데이터 문자열만 필요합니다.

쿠키와의 동기화를 실현할 수 있습니다.왜냐하면 쿠키는 브라우저의 모든 요청에 자동으로 전달되기 때문입니다.따라서 어떤 요청도 설정할 필요가 없습니다.브라우저 주소 표시줄에서 URL을 누르거나 탐색을 통해 URL을 누릅니다.

쿠키 세트 및 제거에는 'cookie-universal-nuxt' 모듈을 사용할 것을 권장합니다.

로그인 후 쿠키 설정

this.$cookies.set('token', 'Bearer '+response.tokens.access_token, { path: '/', maxAge: 60 * 60 * 12 })

로그아웃 시 쿠키 삭제용

this.$cookies.remove('token')

이해를 돕기 위해 문서를 검토하십시오.

또한 API 요청에 @nuxt/http 모듈을 사용하고 있습니다.

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에서 토큰을 얻고 클라이언트는 token store에서 토큰을 가져옵니다.(여기에서는 cookie에서도 얻을 수 있습니다)

그 후 레이아웃의 스토어 데이터 바인딩으로 인해 약간의 수화 문제가 발생할 수 있습니다.이 문제를 해결하려면<no-ssr></no-ssr>이러한 유형의 템플릿 코드를 래핑합니다.

언급URL : https://stackoverflow.com/questions/54789823/middleware-executing-before-vuex-store-restore-from-localstorage

반응형