前端开发那些事儿Vue前端

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

2020-07-01  本文已影响0人  学的会的前端

axios介绍

什么是axios

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

axios特点:

  1. 从浏览器中创建XMLHTTPRequest
  2. 从node.js端创建http请求
  3. 支持PromiseAPI
  4. 拦截请求和响应
  5. 转换请求数据和响应数据
  6. 取消请求
  7. 自动转换JSON数据
  8. 客户端支持防御XSRF

axios拦截器

为什么使用拦截器

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

  1. 在请求和响应被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)
})
  1. 添加拦截器使用use
  2. 移除拦截器使用eject
var myInterceptors = axios.interceptors.request.use()
//移除拦截器
axios.interceptors.request.eject(myInterceptors)
  1. axios自定义实例添加拦截器
//自定义实例
var instance = axios.create()
//添加拦截器
instance.interceptors.request.use()

axios取消请求

  1. 使用cancel token取消请求
  2. 可以使用 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.');
  1. 还可以通过传递一个 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);
        }
    }
});

对于token

token,一般是在登录完成之后,将用户的token通过localStorage或者cookie存在本地,然后用户每次在进入页面的时候,会首先从本地存储中读取token,如果token存在说明用户已经登陆过,则更新vuex中的token状态。然后,在每次请求接口的时候,都会在请求的header中携带token,服务器就可以根据你携带的token来判断你的登录是否过期,如果没有携带,则说明没有登录过。

上一篇下一篇

猜你喜欢

热点阅读