简述vue登录鉴权的业务流程

3,058 阅读2分钟

登录鉴权

前端执行登录获得并保存token,在发送需要登录权限的请求时携带token。

整体流程:

  • 如果用户未登录,当用户使用那些需要登录权限的功能时,跳转到登录页。
  • 登录成功后,用户再次使用那些需要鉴权的功能时,就不会被拦截了。
  • 另外,一般后端也会有鉴权,如果用户需要调用一些有权限的接口时,在请求拦截器中添加token传递给后端,后端就知道我的身份了。

将token保存在vuex中

vue项目刷新瞬间保存在WebStorage中,再从WebStorage获取并重新保存,避免登录状态被清除

按页面效果分为路由鉴权和功能鉴权

路由鉴权

思路:使用VueRouter的路由守卫和meta信息记录,路由守卫根据

// 路由
// meta中有是否需要鉴权的判断
const router = new VueRouter({
  mode: 'hash',
  routes: [
    { path: '/', component: Home },// 不需要鉴权
    { path: '/good/detail/:id', component: Detail },// 商品详情不需要鉴权
    { path: '/cart', component: Cart, meta:{ isAuth:true }}, // 购物车需要鉴权
    { path: '/user', component: User, meta:{ isAuth:true } }, // 用户信息需要鉴权
    { path: '/login', component: Login },
    { path: '/regist', component: Regist }
  ]
})
// 路由守卫
router.beforeEach((to,from,next)=>{
  const { isAuth } = to.meta
  // 假设的一个登录标识
  const token = store.state.user.token
  if (isAuth) {
    // 需要登录,才能过去
    if (token) next()
    else router.push('/login')
    // else location.href = '#/login'
  } else {
    next()
  }
})

功能鉴权

比如商品详情中添加购物车的按钮,未登录时点击跳转到登录页。

思路:创建一个vue指令(directive)能生成一个元素覆盖再购物车按钮上:

Vue.directive('auth', function(el){
  const token = store.state.user.token
  if (!token) { // 鉴权判断,建议使用用户信息,此处图个方便
    el.style.position = 'relative'
    const oDiv = document.createElement('div')
    oDiv.style.position = 'absolute'
    oDiv.style.top = 0
    oDiv.style.bottom = 0
    oDiv.style.left = 0
    oDiv.style.right = 0
    oDiv.style.zIndex = 9999
    oDiv.style.opacity = 0
    oDiv.addEventListener('click', function(){
      router.push('/login')
    })
    el.appendChild(oDiv)
  }
})
<button v-auth @click='addToCart'>加入购物车</button>

其他问题

鉴权失败(或token失效)

后端验证token失败,返回的response中带有{ err: -1 }。

处理逻辑如下:

function errFunc(response){
    if (response.data.err===-1) { // 验证token失败
        vueStore.commit('user/updateToken', null) // 清空vue store
        localStorage.removeItem('token') // 清除localStorage中的token(如果有的话)
        vueRouter.replace('/login') // 跳转登录页
    }
}

将方法放入axios拦截器中

axiosInstance.interceptors.request.use(errFunc)

刷新页面

在app.vue创建之时:

  • 读取sessionstorage中的数据存储在store中,此时用vuex.store的replaceState方法,替换store的根状态
  • 在window.beforeunload事件方法中将store.state存储到sessionstorage中。
// app.vue
export default {
  name: 'app',
  created () {
    // 在页面加载时读取sessionStorage
    if (sessionStorage.getItem('store')) {
      this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem('store'))))
    }
    // 在页面刷新时将store保存到sessionStorage里
    window.addEventListener('beforeunload', () => {
      sessionStorage.setItem('store', JSON.stringify(this.$store.state))
    })
  }
}

最后

本文只是简述,更详细的还是得看花裤衩大佬的手摸手,带你用 vue 撸后台 系列二(登录权限篇)