美文网首页
Axios 配合 React Router 4 实现身份认证

Axios 配合 React Router 4 实现身份认证

作者: 柏丘君 | 来源:发表于2018-06-22 17:31 被阅读0次

上篇文章中,介绍了利用高阶组件,在 React Router 4 中实现了路由守卫。这样的路由守卫,是在前端路由层面上的守卫,属于页面校验机制的第一层:用户能否访问到相应的页面。
事实上,在页面校验时,还有一层需要进行处理:访问接口时的身份认证。某些时候,当用户登陆了系统,可以进入到某个受保护的页面,但在请求接口时,用户的身份令牌(比如 Token)失效了,这种情况下就不能让用户继续留在受保护的页面,而应该重定向至登录页,通过登陆获取新的有效的身份令牌。
一般来说,用户在访问每个接口时,都需要进行一次身份校验,如果用户身份认证失败(HTTP 状态码返回 401),就需要重定向至登录页。但在每次接口调用后,都进行一次判断的话非常麻烦,难以维护。如果我们使用的网络请求的库能够配置响应拦截器就好了,这样就可以对响应进行统一的拦截处理,只需要一份代码就可以处理身份校验。
Axios 中就有这样的功能:axios.interceptors.response 响应拦截器(对应的有 axios.interceptors.request 请求拦截器)。
下面是 Axios 的响应拦截器配合 React Router 4 的一个例子:

import axios from 'axios';
import { message } from 'antd'
import { ERROR } from '../config/error.config';
import createHistory from 'history/createHashHistory';

// 响应拦截
axios.interceptors.response.use((response) => {
    return response
}, (err) => {
    if(err.response.status === '401'){
        message.error(ERROR.LOGIN_EXPIRESSED);
        localStorage.removeItem('__config_center_token');
        localStorage.removeItem('__config_center_niceName');
        localStorage.removeItem('__config_center_imageUrl');
        const history = createHistory();
        setTimeout(() => {
            history.push('/login')
        },1500)
    }
    return Promise.reject(err)
})

当身份认证失败时,首先进行全局的跳转提示,然后移除 LocalStorage 中保存的原始数据,再通过 createHashHistory 的实例(我在项目中使用的是 HashHistory,如果使用的是 BrowserHistory 的话,需要引入 creatBrowserHistory)进行路由的跳转。
在使用 React Router 4 时,只有在 Route 组件内部才能通过 Props 获取到 history 实例,而在非 Route 组件内部想再使用 history 的功能的话,只有通过 createHashHistory 再创建一个了。

一点优化建议

上面的请求中,每个请求都会被拦截,如果一次只进行一个请求还好说,但如果同时请求多个接口,假如此时身份验证失败了,就会进行多次的弹窗提醒以及路由跳转,这个就很不友好,因此,对于一次性发出多个请求的情况,如果这些请求都失败了,最好只弹窗提醒一次。我的解决方案是加一个哨兵变量:

import { message } from 'antd'
import { ERROR } from '../config/error.config';
import createHistory from 'history/createHashHistory';
let cancelFlag:boolean = false;

// 响应拦截
axios.interceptors.response.use((response) => {
    return response
}, (err) => {
    if(err.response.status === '401'){
        if(cancelFlag) return Promise.reject(err);
        cancelFlag = true;
        message.error(ERROR.LOGIN_EXPIRESSED);
        localStorage.removeItem('__config_center_token');
        localStorage.removeItem('__config_center_niceName');
        localStorage.removeItem('__config_center_imageUrl');
        const history = createHistory();
        setTimeout(() => {
            history.push('/login')
            setTimeout(() => {
                cancelFlag = false;
            },1000)
        },1500)
    }
    return Promise.reject(err)
})

以上,就避免了多次弹窗提醒和路由跳转的情况。

完。

相关文章

网友评论

      本文标题:Axios 配合 React Router 4 实现身份认证

      本文链接:https://www.haomeiwen.com/subject/tjakyftx.html