当前位置: 首页 > Web前端 > vue.js

利用axios和vue-router钩子函数实现登录权限控制,和实现全局请求配置

时间:2023-03-31 22:48:44 vue.js

使用axios和vue-routerhook函数实现登录权限控制,实现全局请求配置对于刚入门的开发者,有人用过vue-resource(其实是一个已经被官方废弃的库,现在推荐使用axios)或aioxs,但大多数都是在各个组件中无一例外地直接调用。库的API用于发出请求。当时我第一次做Vue项目的公司也是这样做的。面试官告诉我,这个可能没问题,但是不够规范,不能方便的管理所有请求的参数配置。最近自己做的一个vue项目,于是想了想,结果也和我想的一样,确实涉及到很多请求参数的统一配置,比如token,userid等,需要传给后台验证参数,如果我们每个request都传入,项目可能有几十个,上百个request,一个一个去添加,很麻烦很傻。先看我的文件结构,我创建了一个http.js,这是我用来二次打包axios和管理全局请求的文件,router.js配置路由文件,main.js是vue的入口文件,我们主要依靠这三个文件来实现路由访问控制。http.js的内容其实很简单importVuefrom'vue';importaxiosfrom'axios';importqsfrom'qs';importrouterfrom'./router';importmd5from'js-md5';letvm=newVue();axios.defaults.timeout=60000;//超时之前,所有请求都会等待60秒先使用请求拦截器对发送的请求体进行相应的配置,比如添加一些必要的参数,可能会用到token等后台认证,一些接口加密方式在请求加载时也可以统一显示functiongetHeaderKey(){//一种加密方式}axios.interceptors.request.use(config=>{//config.data=JSON.stringify(config.data);if(localStorage.token){//判断是否有token,如果有则在每个http头中添加一个tokenconfig.headers["X-Access-Token"]=`${localStorage.token}`;//加载vm.$loading();}//接口加密验证config.headers["channelType"]='wx_applet';config.headers["for_valid"]=getHeaderKey();返回配置;},err=>{//关闭加载vm.$loading.close();返回Promise.reject(err);});然后使用响应拦截器判断响应体返回的一些参数,比如接口是否返回token失效等,统一管理token失效的状态码需要和后台约定,不一定是401,甚至可以在post或者下面具体封装的get方法中判断。//http响应拦截器axios.interceptors.response.use(response=>{//关闭加载vm.$loading.close();returnresponse;},error=>{//关闭加载vm.$loading.close();if(error.response){vm.$toast.center("返回码:"+error.response.status+';'+'请求错误');switch(error.response.status){case401://返回401清除token信息,跳转到登录页面localStorage.removeItem('token');localStorage.clear();router.replace({path:'login',query:{redirect:router.currentRoute.fullPath}});break;}}returnPromise.reject(error)//返回接口返回的错误信息});接下来封装具体的请求方法,可以全局管理不同的请求方法,因为我们整个项目使用的是post请求,我这里写了全局请求需要的reqfrom和appkey,具体怎么封装就不说了这里get方法,跟post基本一样。可能有一些开发者忽略的问题,就是当请求是form格式时,需要使用qs包的stringify方法对参数进行格式化,如果是json格式则不需要。我们的界面正好有这两种格式,所以我也做了区分。因为接口是post请求,所以把它的判断写在post里面。token失效判断我这里也是按照实际接口写的,如果失败了,会跳转到登录页面appkey:组织代码(唯一)if(localStorage.jsonObject){letuserObj=JSON.parse(localStorage.jsonObject);data.userid=userObj.userid?userObj.userid:'';}data.reqfrom=vm.$api。请求自;data.appkey=vm.$api.appKey;if(type==='json'){axios.defaults.headers.post['Content-Type']='application/json;charset=UTF-8';data.mobilePhone=localStorage.mobilePhone}else{axios.defaults.headers.post['Content-Type']='application/x-www-form-urlencoded;charset=UTF-8';data=qs.stringify(数据);}returnnewPromise((resolve,reject)=>{axios.post(url,data).then(response=>{letcode=response.data.code;if(type!=='json'){if(response.data.msg=='tokenhasexpired'||code=='99999'||code=='99997'||code=='40001'||code=='99996'||code=='"99998'||code=='9999'){localStorage.removeItem('token');localStorage.removeItem('jsonObject');router.replace({path:'login',query:{redirect:router.currentRoute.fullPath}})}}resolve(response.data);},err=>{if(err.message.indexOf('timeout')!==-1){vm.$toast.bottom('requesttimeout')}reject(err);})})}接下来在main.js中,将封装好的方法挂载到vue实例中,然后就可以将各个组件调用import{post,get}from"./http";Vue.prototype.$post=post;Vue.prototype.$get=get;页面是否需要登录才能访问,这个用到了路由的meta信息结合路由钩子函数beforeEach来判断,如下。这里在router.jsmain.js中的判断逻辑也很简单,如果需要登录权限,就去获取locaStorage中的token,如果不需要,你可以放手如果需要登录权限但是本地不存在token下一步跳转到登录页面如何判断token是否存在nisinvalid已经写在上面的http.js中了。如果接口返回无效,也会跳转到登录页面。至此,我们的登录配置就完成了。当然,页面可能远不止这么简单的逻辑判断,还会有更复杂的判断,需要根据各个项目的实际情况来添加。router.beforeEach((to,from,next)=>{if(to.meta.requireAuth){//判断路由是否需要登录权限letjsonObject=JSON.parse(localStorage.getItem('jsonObject'));//容错,如果localStorage中没有对象,则初始化一个空对象if(jsonObject==null){jsonObject={};}else{next({path:'/login',//query:{redirect:from.fullPath}query:{redirect:router.currentRoute.fullPath}})}}else{next();}});