借助axios的拦截器实现Vue.js中登陆状态校验

axios介绍

什么是axios

axios是一个基于Promise的HTTP库,可以用在浏览器或node.js中。

axios特点:

  • 从浏览器中创建XMLHTTPRequest
  • 从node.js端创建http请求
  • 支持PromiseAPI
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 自动转换JSON数据
  • 客户端支持防御XSRF
  • axios拦截器

    为什么使用拦截器

    页面发送http请求,很多情况我们要对请求和其响应进行特定的处理;例如每个请求都附带后端返回的token,拿到response之前loading动画的展示等。如果请求数非常多,这样处理起来会非常的麻烦,程序的优雅性也会大打折扣。在这种情况下,axios为开发者提供了这样一个API:拦截器。拦截器分为 请求(request)拦截器和 响应(response)拦截器。

  • 在请求和响应被then或catch处理前拦截它们。
  • //添加请求拦截器
    axios.interceptors.request.use(function(config){
      //在请求发送之前做些什么
      return config
    },function(error){
      //对请求错误做些什么
      return Promise.reject(error)
    //添加响应请求
    axios.interceptors.reponse.use(function(reponse){
      //对响应数据做些什么
      return reponse
    },function(error){
      //对响应错误做些什么
      return Promise.reject(error)
    
  • 添加拦截器使用use
  • 移除拦截器使用eject
    var myInterceptors = axios.interceptors.request.use()
    //移除拦截器
    axios.interceptors.request.eject(myInterceptors)
    
  • axios自定义实例添加拦截器
  • //自定义实例
    var instance = axios.create()
    //添加拦截器
    instance.interceptors.request.use()
    

    axios取消请求

  • 使用cancel token取消请求
  • 可以使用 CancelToken.source 工厂方法创建 cancel token,
  • var CancelToken = axios.CancelToken;
    var source = CancelToken.source();
    axios.get('/user/12345', {
      cancelToken: source.token
    }).catch(function(thrown) {
      if (axios.isCancel(thrown)) {
        console.log('Request canceled', thrown.message);
      } else {
        // 处理错误
    // 取消请求(message 参数是可选的)
    source.cancel('Operation canceled by the user.');
    
  • 还可以通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token:
  • var CancelToken = axios.CancelToken;
    var cancel;
    axios.get('/user/12345', {
      cancelToken: new CancelToken(function executor(c) {
        // executor 函数接收一个 cancel 函数作为参数
        cancel = c;
    // 取消请求
    cancel();
    

    借助axios的拦截器实现Vue.js中登陆状态校验

    后台系统中,不是每个页面都需要登录权限,所以要对需要进行登录权限的页面做好标记,使用路由的meta标签

    path: '/userInfo', name: '/userInfo', meta: { requireAuth: true // 该路由需要登录权限校验 component: userInfo path: '/userInfo', name: '/userInfo', // 该路由需要登录权限校验 component: userInfo

    定义一起全局前置守卫,每次跳转路由,进行权限校验

    router.beforeEach((to,from,next) => {
      if(to.meta.requireAuth){ //如果路由需要校验权限
        从vuex拿出token码,说明已经登录
        (前端的Token可以伪造,并不靠谱)
        if(store.state.token){
          next() //正常跳转页面
        }else{
          next({
            path: "/login",
            query: {redirect: to.fullPath}
            /*将跳转的路由地址作为参数带给登录页,登录成功后跳转回改页面 */
      }else {
        //如果不要校验,直接进入登录页
        next()
    

    但以上的实现存在问题,token可以伪造,这是其一,其二,token前端存在,但后端可能已经失效。所以采用后端的一层校验,确保权限token的准确性。就要使用到axios中的拦截器(interceptors)。

    实现思路:如果前端有token ,每次发送请求的时候,把token 发送给后端,后端按到token后,进行校验,之后把校验结果在接口中反馈
    请求拦截:

    axios.interceptors.request.use(requestConfig => {
      if(store.state.token){
        config.headers.Authorization = ${store.state.token}
      return requestConfig
    },err => {
      return Promise.reject(err)
    

    响应拦截:后端拿到Token,发现token ,返回401(前后端约定好的),此时前端就知道作何处理

    // response interceptor
    axios.interceptors.response.use(
        response => {
            // 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据
            // 否则的话抛出错误
            if (response.status === 200) {
                return Promise.resolve(response);
            } else {
                return Promise.reject(response);
        // 服务器状态码不是2开头的的情况
        // 这里可以跟你们的后台开发人员协商好统一的错误状态码
        // 然后根据返回的状态码进行一些操作,例如登录过期提示,错误提示等等
        // 下面列举几个常见的操作,其他需求可自行扩展
        error => {
            if (error.response.status) {
                switch (error.response.status) {
                    // 401: 未登录
                    // 未登录则跳转登录页面,并携带当前页面的路径
                    // 在登录成功后返回当前页面,这一步需要在登录页操作。
                    case 401:
                        router.replace({
                            path: '/login',
                            query: {
                                redirect: router.currentRoute.fullPath
                        break;
                    // 403 token过期
                    // 登录过期对用户进行提示
                    // 清除本地token和清空vuex中token对象
                    // 跳转登录页面
                    case 403:
                          Message({
                            message: '登录过期,请重新登录',
                            duration: 1000,
                            forbidClick: true
                        // 清除token
                        localStorage.removeItem('token');
                        store.commit('loginSuccess', null);
                        // 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
                        setTimeout(() => {
                            router.replace({
                                path: '/login',
                                query: {
                                    redirect: router.currentRoute.fullPath
                        }, 1000);
                        break;
                    // 404请求不存在
                    case 404:
                        Message({
                            message: '网络请求不存在',
                            duration: 1500,
                            forbidClick: true
                        break;
                    // 其他错误,直接抛出错误提示
                    default:
                        Message({
                            message: error.response.data.message,
                            duration: 1500,
                            forbidClick: true
                return Promise.reject(error.response);