基于Vue+VueRouter+Vuex+Axios的用户登录态路由级和接口级拦截的原理与实现

简介: 前后端分离开发、独立部署,为前端的开发人员提供了极大的便利,同时也带来了新的挑战。

前后端分离带来的问题


  1. 在路由级,模块之间的切换、跳转需要前端进行独立的维护


  1. 在接口级,前后端数据交互由接口进行连接(异步)


这是重点:前端需要根据用户的登录态或角色身份进行权限控制拦截,以展示对应的功能模块或者是展示对应的数据。


接下来胡哥就给小伙伴分享下在实际项目中的基于Vue+VueRouter+Vuex+Axios的用户登录态路由级和接口级拦截的原理与实现。


路由级拦截


1. 问题思考


  • 怎么拦截


// 借助于VueRouter的钩子函数beforeEach,判断是否有权限进入,执行next()或next(false) router.beforeEach((to, from ,next) => { // next() 通过,允许进入 // next(false) 禁止,不允许进入该模块 })


  • 拦谁


// 在VueRouter的路由配置项中,增加meta属性,设置是否需要权限验证的标记
   // 用户中心路由
   {
     path: 'user',
     name: 'User',
     Component: User,
     meta: {
         // 需要权限验证
         requireAuth: true
     }
   }


2. 实现方案


  • 安装vue-router


npm i vue-router -D


  • 定义路由以及路由设置权限标志


import Vue from 'vue'
  import VueRouter from 'vue-router'
  Vue.use(VueRouter)
  const router = new VueRouter({
    // 路由规则
    routes: [
      {
        path: '/',
        name: 'Home',
        // 引入的模块默认是已经引入并定义了,这里不多描述
        component: Home,
        children: [
          {
            path: 'index',
            name: 'Index',
            component: Index,
            // 定义元信息
            meta: {
              // 权限验证标记 false 不进行校验拦截
              requireAuth: false
            }
          },
          {
            path: 'user',
            name: 'User',
            component: User,
            meta: {
              // 权限验证标记 true 进行校验拦截
              requireAuth: true
            }
          },
          {
            path: 'login',
            name: 'Login',
            component: Login,
            meta: {
              // 权限验证标记 false 不进行校验拦截
              requireAuth: false
            }
          }
        ]
      }
    ]
  })


  • 权限拦截判定


以用户登录态作为标志,进行登录验证


const router = new VueRouter({
    routes: [
      // ...
    ]
  })    
  // 权限拦截-beforeEach路由钩子函数
  router.beforeEach (to, from, next) {
    // to 目的路由对象 from 来源路由对象
    if (to.match.some(rocode => recode.meta.requireAuth)) {
      /**
      * 登录状态-可使用aixos进行请求,拉取服务器数据,获取用户登录状态
      * 强烈建议在本地使用localStorage或sessionStorage和vuex共同管理用户登录态,避免每次进入时都拉取服务器端接口以验证用户是否登录,额外消耗对服务器的请求,提升用户体验
      * 如果已登录,则更新store中存储的loginName -- 详细查看下面的store配置
      * 未登录,则直接跳转走
      */ 
      let isLogin = 已登录 ? true : false
      // 执行拦截判定
      if (!isLogin) {
        // 跳转到登录模块
        // 处理方式一:借助next()方法
        next({
          name: 'Login',
          replace: 'true',
          // redirectUrl 用于标记登录后回跳的地址
          redirectUrl: to.fullPath
        })
        // 处理方式二:使用window.loaction.href方式,需要执行next(false)配合使用
        window.location.href = '指定的登录地址?redirectUrl=' + to.fullPath
        next(false)
      } else {
        // 已登录,直接进入
        next()
      }  
    } else {
      // 不执行拦截,直接进入该路由
      next()
    }
  } 


接口级拦截


1. 问题思考


  • 怎么拦截


借助axios的拦截器:
  interceptors.request.use 请求拦截器
  interceptors.response.use 响应拦截器


  • 拦谁


设置特定的接口地址白名单,用于是否进行用户登录态权限判定


不是所有的接口都要进行拦截的,比如:
    1. 发送和获取登录信息的接口
    2. 发送注册信息的接口
    3. 其他不需要用户态的接口


2. 实现方案


  • 安装axios


npm i axios -D


  • 引入axios,添加拦截器


import axios from 'axios'
  import router from '@/router'
  // 具体数据仓库对象store配置请往下看
  import store from '@/store'
  const $http = axios.create({
    // 基本配置项
  })
  // 定义接口地址白名单
  const allowUrls = [
    '/getUserInfo',
    '/addUserInfo'
  ]
  // 请求拦截器 -- 发送请求前,判断是否存在登录信息
  $http.interceptors.resquest.use((config) => {
    // config.url 是请求的URL地址
    if (allowUrls.includes(config.url)) {
      // 判断是否登录 --- 本地信息以及vuex的store信息进行判定
      let isLogin = locationStorage.getItem('isLogin')
      if (!isLogin || !store.state.loginName) {
        // 携带当路由地址,跳转登录
        // router.currentRoute.fullPath
      } else {
        return config
      }
    } else {
      // 不需要判定则直接返回config配置
      return config
    }
  })
  // 响应拦截器
  $http.interceptors.response.use((res) => {
    // 判断是否需要验证权限
    if (allowUrls.includes(res.config.url)) {
      // 判断是否登录 --- 本地信息、vuex的store信息以及后端服务器响应回来的是否登录的标记
      let isLogin = locationStorage.getItem('isLogin')
      // 约定 code 10011 表示未登录
      if (!isLogin || !store.state.loginName || res.data.code === 10011) {
        // 携带当路由地址,跳转登录
        // router.currentRoute.fullPath
      } else {
        return config
      }
    } else {
      return res
    }
  })


数据仓库sotre


1. 下载安装vuex


npm i vuex -D


2. 配置相关项


import Vue from 'vue'
 import Vuex from 'vuex'
 Vue.use(Vuex)
 const store =  new Vuex.Store({
  state: {
    // 用户登录后,获取昵称
    loginName: ''
  },
  mutations: {
    updateLoginInfo (state, loginName) {
      state.loginName = loginName
    }   
  }
 })



相关文章
|
10天前
|
JavaScript 前端开发 Serverless
Vue.js的介绍、原理、用法、经典案例代码以及注意事项
Vue.js的介绍、原理、用法、经典案例代码以及注意事项
26 2
|
30天前
|
JavaScript
Vue3中props的原理与使用
Vue3中props的原理与使用
15 0
|
30天前
|
JavaScript
Vue 中如何模块化使用 Vuex
Vue 中如何模块化使用 Vuex
14 0
|
30天前
|
JavaScript 前端开发
vue中nextTick使用以及原理
vue中nextTick使用以及原理
11 0
|
10天前
|
JavaScript API 开发者
Vue中双向数据绑定是如何实现的?底层原理简介
Vue中双向数据绑定是如何实现的?底层原理简介
10 4
|
10天前
|
JavaScript 安全 前端开发
vue怎么处理跨域,原理?
vue怎么处理跨域,原理?
18 2
|
14天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的《数据库系统原理》课程平台附带文章和源代码设计说明文档ppt
基于ssm+vue.js+uniapp小程序的《数据库系统原理》课程平台附带文章和源代码设计说明文档ppt
19 1
|
15天前
|
JavaScript 开发者
[vue2/vue3] -- 深入剖析v-model的原理、父子组件双向绑定的多种写法
[vue2/vue3] -- 深入剖析v-model的原理、父子组件双向绑定的多种写法
[vue2/vue3] -- 深入剖析v-model的原理、父子组件双向绑定的多种写法
|
21天前
|
前端开发 JavaScript
1天搞定SpringBoot+Vue全栈开发 (7)Axios网络请求
1天搞定SpringBoot+Vue全栈开发 (7)Axios网络请求
|
30天前
|
JavaScript 前端开发
深入了解前端框架Vue.js的响应式原理
本文将深入探讨Vue.js前端框架的核心特性之一——响应式原理。通过分析Vue.js中的数据绑定、依赖追踪和虚拟DOM等机制,读者将对Vue.js的响应式系统有更深入的理解,从而能够更好地利用Vue.js构建灵活、高效的前端应用。