[聚合文章] vuejs用户认证实例

Vue.js 2017-11-30 17 阅读

在本例子中,使用的请求方法都是使用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和用户信息清除,跳转到登录页或者不需认证的首页即可。

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。