专栏首页胡哥有话说基于Vue+VueRouter+Vuex+Axios的用户登录态路由级和接口级拦截的原理与实现

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

前言

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

前后端分离带来的问题

基于前端分离带来的问题

  1. 在路由级,模块之间的切换、跳转需要前端进行独立的维护
  2. 在接口级,前后端数据交互由接口进行连接(异步)

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

接下来胡哥就给小伙伴分享下在实际项目中的基于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 } } })

后记

以上就是胡哥今天给大家分享的内容,喜欢的小伙伴记得收藏、转发、点击在看呦…

长按扫码关注,更帅更漂亮呦!

胡哥有话说

胡哥有话说,一个有技术,有情怀的胡哥!京东开放平台首席前端攻城狮。与你一起聊聊大前端,分享前端系统架构,框架实现原理,最新最高效的技术实践!

本文分享自微信公众号 - 胡哥有话说(hugeyouhuashuo)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-06-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Node.js 入门你需要知道的 10 个问题

    Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。它是一个开源和跨平台的服务端应用程序。任何人都可以编写 JavaScri...

    五月君
  • 基于Egg框架的日志链路追踪实践

    实现全链路日志追踪,便于日志监控、问题排查、接口响应耗时数据统计等,首先 API 接口服务接收到调用方请求,根据调用方传的 traceId,在该次调用链中处理业...

    五月君
  • Kafka消费者 之 如何提交消息的偏移量

    由于消费者模块的知识涉及太多,所以决定先按模块来整理知识,最后再进行知识模块汇总。

    create17
  • 前后端API交互如何保证数据安全性?

    前后端分离的开发方式,我们以接口为标准来进行推动,定义好接口,各自开发自己的功能,最后进行联调整合。无论是开发原生的APP还是webapp还是PC端的软件,只要...

    黄泽杰
  • 分享 10 道 Nodejs 进程相关面试题

    关于线程和进程是服务端一个很基础的概念,在文章 Node.js进阶之进程与线程 中介绍了进程与线程的概念之后又给出了在 Node.js 中的进程和线程的实际应用...

    五月君
  • 微服务Consul系列之集群搭建

    在上一篇中讲解了Consul的安装、部署、基本的使用,使得大家有一个基本的了解,本节开始重点Consul集群搭建,官方推荐3~5台Server,因为在异常处理中...

    五月君
  • C#迭代器与LINQ查询操作符

    (1)使用 针对集合类型编写foreach代码块,都是在使用迭代器 集合类型实现了IEnumerable接口 都有一个GetEnumerator方法 (...

    祝你万事顺利
  • Caffeine Cache 进程缓存之王

    互联网软件神速发展,用户的体验度是判断一个软件好坏的重要原因,所以缓存就是必不可少的一个神器。在多线程高并发场景中往往是离不开cache的,需要根据不同的应用场...

    黄泽杰
  • Node.js结合RabbitMQ延迟队列实现定时任务

    RabbitMQ本身是不支持的,可以通过它提供的两个特性Time-To-Live and Expiration、Dead Letter Exchanges来实现...

    五月君
  • 浅入深出Vue:环境搭建

    这里同样的,有固态硬盘的童鞋可以安装到固态硬盘,不过这里有个小问题就是 在选择目录的时候会卡死一小会儿。可能是若羽的机器性能不太好。

    若羽

扫码关注云+社区

领取腾讯云代金券