url带token触发UserLogin存数据--全局权限控制

main.js引入permission.js

permission中使用router.beforeEach进行全局的路由拦截。

场景:
1、任何用户,都要获取用户地理位置。getUserLocation接口
2、免登录白名单不需要登录接口,非免登录白名单需要登录信息。getUserLogin接口获取用户信息
逻辑:
单页面应用,main.js只加载一次,路由跳转不再次进入。所以getUserLocation接口这里调用

1、main.js中
store.dispatch('getUserLocation').then(() => {
    console.log('位置成功')
}, () => {
    console.log('位置失败')
}).finally(() => { // 为了保证一定加载完接口用finally
    app.use(router)
    app.mount('#app');
})

获取用户信息,使用了.then方法。要有new Promise 进行返回才ok


image.png

getUserLogin接口调用,需要在router.beforeEach,看时机调用。
路由中设置meta.auth为true,这种页面需要用到vuex中的oldToken做请求接口头中的auth。所以必要的时候要调用getUserLogin接口。
逻辑:

const auth = to.meta?.auth
// 当该页面需要权限&&该页面的url上有token&&vuex中没有存储过
if (auth && to.query.token && !store.getters.userInfo.ecode) {
    store.dispatch('init').then((res) => {
      if(JSON.stringify(res)!=='{}'){
        next({ // 再次进入该路由,由于vuex中存了userInfo,会打印aaaa
          ...to
        })
      }else{ // 当oldToken请求userLogin返回resultCode: -99时候,res为{}
        next(false) // 中断当前路由,接口-99,axios中的相应拦截器,跳转了异常页面,异常页面属于免登录白名单
      }
    }).catch(() => {
      next('/emptyPage') //请求userLogin接口过程中接口报错进入空白
    })
  } else {
    console.log('aaaa')
    next()
  }

store.dispatch('init')发生了什么?

async init({ dispatch, commit }) {
            // 从url中获取token=>放入存储,之后每次更新
            let { token = '', ecode = '' } = Tools.getUrlQuery(window.location.href);
            commit('SET_OLDTOKEN', token)
            if (!token) {
                return Promise.reject();
            }
            try {
                const params = {
                    token,
                    ecode
                }
                return await dispatch('getUserLogin', params)
            } catch (err) {
                return Promise.reject()
            }
        },
        async getUserLogin({ commit }, params) {
            if (!params.token) {
                return Promise.reject()
            }
            try {
                const resData = await getUserLogin(params)
                const userInfo = resData?.user || {};
                commit('SET_USERINFO', userInfo)
                return Promise.resolve(userInfo)
            } catch (err) {
                return Promise.reject()
            }
        },

需要注意的点:
1、vuex存储数据,页面刷新数据丢失。需要使用持久化缓存
npm install --save vuex-persistedstate
import createPersistedState from "vuex-persistedstate";
只需要在actions的同级下配置:

    plugins: [
        createPersistedState({
          key: "vuexInfo", // 存储的key
          storage: window.sessionStorage, // 使用的sessionStorage
        })
    ]
// storage: window.localStorage, //选择 localStorage 进行存储

注意这里,使用了持久化插件后,不用你赋值,直接会赋值的

    state() {
        return { //storage中的值直接赋值,不用单独再赋值
            userInfo: {},
            token: '', // 子工程接口请求回来的token
            oldToken: '', // url上自带的token
            userLocation: {}
        }
    },

image.png

想要使用存储到cookie的配置如下:
image.png

具体网址:
https://blog.csdn.net/weixin_55042716/article/details/123107602

===============继续===================
那我使用持久化存储解决了什么问题呢?
1、我页面带token的,第一次请求完getUserLogin,刷新页面,vuex中还是有,不用再调接口
2、我从带token的页面,跳转到不带token的页面。每次热更新页面,加载页面,不怕vuex中数据丢失,造成的接口headers中auth为null造成的问题。
那给我带来了什么麻烦么?
我sessionStorage进行数据存储。我需要彻底关闭网页才能消掉缓存。
我在地址栏输入网址,走getUserLogin,存vuex,持久存。刷新还有。我更换账户token,该地址栏输入新的网址,url上的token肯定是新的。但是由于我持久化存储。不可能再次走dispatch('init'),拿取的数据就不对

===================我要怎么做====================
清除缓存。
问题1、如何清。怎么存的怎么清除。用commit()清除vuex中state的值,sessionStorage中的就会清掉。
问题2、在哪里清除。临界条件是什么?
肯定是全局清。
main.js?工程加载会清,从a页面push到b页面不会清
似乎满足了条件。
main.js是加载全局资源的,在这里处理缓存问题感觉不妥当。

export function clearStorage() {
  store.commit("setUser", {});
  store.commit("SET_OLDTOKEN", "");
  store.commit("setOrganizations", []);
}

permission.js的路由拦截器外面?
只要加载页面就会进入路由拦截器。看来也能清掉。但是清掉后。从带token的网址跳转到不带token的网址,也把缓存清掉了,注意这里vuex中是有的。之前做的持久化缓存没意义了。
解决:加清除的判断

  const auth = to.meta?.auth;
  let { token = "" } = Tools.getUrlQuery(window.location.href);
  let storeToken = store.getters.oldToken;
  // url有token并且store不一致,清缓存
  // 浏览器缓存原因,一个页签换token要敲2次enter,uuid待加
  if (token && token !== storeToken) {
    clearStorage();
  }

==============经历=======================
beforeEach中调用next(),必须逻辑很清晰,多一个next(),少一个next()都报错或者警告

axios中统一拦截,接口返回-99,跳转到异常界面

你可能感兴趣的:(url带token触发UserLogin存数据--全局权限控制)