
在本例子中,使用的请求方法都是使用axios,vuejs的官方推荐。
安装与使用axios
npm install axios
在main.js(如果你使用的是vue-cli脚手架搭建的项目)中引入
import axios from 'axios' Vue.prototype.$http = axios
之后使用小栗子即是
this.$http.get(URL).then(response => { // success callback }, response => { // error callback })
登录
在登录部分,登录成功后,将服务器返回的token存在sessionstorage中,当然也可以放在localstorage,或者使用vuex的方式存储token数据和用户信息。
var url = "/api/web/login"; var data={username:this.username,password:this.password}; this.$http({method:"get",url:url,auth:data}).then(response => { if(response.status==200){ // this.$store.state.token=response.data.token; sessionStorage.token = response.data.token; sessionStorage.username = response.data.username; this.$router.push(this.$route.query.redirect||'/'); //登录成功则跳转到首页 } }).catch(function(error){ //error });
路由配置
以前写路由配置的时候即只是如下示例:
import Vue from 'vue' import Router from 'vue-router' import Web from '@/components/Web' import Dashboard from '@/components/Dashboard' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'Web', component: Web, children:[ { path: "/", name: 'Dashboard', component: Dashboard } ] } ] })
当打包构建应用时,Javascript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。这就是懒加载。
改成如下的方式即可实现
import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) const router = new Router({ routes: [ { path: '/', name: 'Web', component(resolve) { require.ensure(['@/components/Web.vue'], () => { resolve(require('@/components/Web.vue')); }); }, meta: { requireAuth: true }, children:[ { path:"/", name:'Dashboard', component(resolve) { require.ensure(['@/components/Dashboard.vue'], () => { resolve(require('@/components/Dashboard.vue')); }); }, meta: { requireAuth: true } }, { path:'/login', name:'Login', component(resolve) { require.ensure(['@/components/Login.vue'], () => { resolve(require('@/components/Login.vue')); }); }, } ] })
同时,还加入了路由元信息,配置了meta-requireAuth字段,来判断在这个路由中是否需要身份认证
利用”导航守卫“来检查该字段
router.beforeEach((to, from, next) => { let token = sessionStorage.token;//从sessionstorage中获取,或者利用localstorage和vuex if(to.meta.requireAuth) { //如果该路由需要登录 if(token) { //且token是存在的,则可以进入该路由 next() } else { next({ path: '/login', //否则跳转到登录页面, query: { redirect: to.fullPath }//将跳转的路由path作为参数,登录成功后跳转到该路由 }) } } else { next() } }) export default router
[tip:]
每个守卫方法接收三个参数:
- to: Route: 即将要进入的目标 路由对象
- from: Route: 当前导航正要离开的路由
- next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
1) next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
2) next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
3) next(‘/‘) 或者 next({ path: ‘/‘ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。
4) next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
axios拦截器
在做了以上情况之后,你只是做到了表面上的前端路由控制,接下来我们使用axios拦截器实现以下功能:
1.登陆后,为了保持认证的请求,在每次请求的头部加上登录成功时返回的token信息
2.发送不合法的请求或者在没有认证的情况下发送请求后,如果服务器返回的状态是401(Unauthorized 未授权)或者403(Forbidden 拒绝),则跳转到登录页面。
发起每次请求时,都在头部加上token字段,让服务器验证token是否有效,如果后端接口返回 401 或者403 ,则让用户重新登录,并清除token信息。
axios.interceptors.request.use( config=>{ if(sessionStorage.token){ config.auth = {username:sessionStorage.token,password:""}; } return config; }, err=>{ return Promise.reject(err); } );
在这里,我是将token信息作为username,password置为空,赋予axios的auth字段,这样会直接进行base64编码作为基础认证传给服务器。
当然也可以使用以下方式将token赋予请求头部的Authorization字段返回给服务器。
config.headers.Authorization = `token ${sessionStoreage.token}`;
axios.interceptors.response.use( response => { return response; }, error => { if (error.response) { switch (error.response.status) { case 401: // 返回 401 清除token信息并跳转到登录页面 sessionStorage.token=""; router.replace({ path: '/login', query: {redirect: router.currentRoute.fullPath} }); break; case 403: // 返回 401 清除token信息并跳转到登录页面 sessionStorage.token=""; router.replace({ path: '/login', query: {redirect: router.currentRoute.fullPath} }) break; } } return Promise.reject(error.response.data) // 返回接口返回的错误信息 } );
至此,整个用户认证实例即结束。
登出的时候,只要将保存在storage里的token和用户信息清除,跳转到登录页或者不需认证的首页即可。
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。