React中结合flyio与fetch-jsonp处理跨域登录传递Token问题

这里仅以flyio与fetch-jsonp结合作为示例(token存放在cookie中),具体代码逻辑视项目而定

要点
- flyio拦截器中执行异步任务
- 发送jsonp请求

现在有两个不同域网站 a网站 & b网站
1. 当访问a网站时检测有无token,无token则向b网站发送jsonp请求换取token,在token请求回来之前暂不受理其他任何请求(防止重复发送jsonp请求),获取后将token写入cookie,写入完毕后,跳转到b网站进行登录,有token则进行下一步。
2. 已有token,a网站的响应拦截器则检测token是否过期,未过期则放行,过期则向b网站发送jsonp请求更新token,更新成功刷新页面。

主要代码

import React from 'react';
import {Router, Route} from 'react-router-dom';
import fly from 'flyio';
import Cookies from 'js-cookie';
import fetchJsonp from 'fetch-jsonp';

fly.config.withCredentials = true;
fly.config.baseURL = "/";

class Root extends React.Component {
    componentWillMount() {
        let _this = this;
        fly.interceptors.request.use(function (request) {
            if (!Cookies.get('token')) {
                //锁定当前实例,后续请求会在拦截器外排队,防止重复请求,当前请求也会等待jsonp的执行完毕
                fly.lock();
                return _this.handleRequestJsonp(request);
            } else {
                request.headers["token"] = Cookies.get('token');
                return request;
            }
        });

        fly.interceptors.response.use(
            function (response) {
                if (response.headers['isTokenValid'] === '0') {
                    this.lock(); //无效,锁定响应拦截器,防止重复jsonp请求
                    _this.handleResponseJsonp(this, response);
                } else {
                    return response;
                }
            },
            function (error) {
                _this.handleError(error);
                return Promise.reject(error);
            }
        );
    }

    handleRequestJsonp = (request) => {
        // fetchJsonp中的请求url必须以(.jsonp)结尾
        fetchJsonp(`b网站接口地址.jsonp`).then(function(response) {
            return response.json();
        }).then(function(json) {
            Cookies.set('token', json.token);
          // 可能会根据其他条件判断是否需要跳转到登录页面,如无需跳转则返回request,则会继续发送原来的请求,如要继续发送原来的请求 需要加入 request.headers['token'] = json.token;,这里简单处理直接跳转到登录页面
            window.location.href = 'b网站登录页面地址';
        }).catch(function(ex) {
            console.log(ex);
        }).finally(() => {
            fly.unlock(); // 解封当前实例,后续请求队列依次发送
        });
    };

    handleResponseJsonp = (that, response) => {
        fetchJsonp(`b网站更新token接口地址.jsonp`).then(function(result) {
            return result.json();
        }).then(function(json) {
            Cookies.remove('token');
            Cookies.set('token', json.token);
        }).finally(() => {
            return that.unlock(); 
        }).then(() => {
            window.location.reload(); // 刷新页面,这里也可以重发当前请求,具体见flyio官网
        }).catch(function(ex) {
            console.log(ex);
        });
    };

    render() {
        return (
            <div>Root</div>
        )
    }
}

export default Root;

猜你喜欢

转载自blog.csdn.net/roamingcode/article/details/81697543