locatstorage缓存管理token值

export default class Authority {
  /**
   * 保存token
   *
   * @param data
   * @param key
   * @return void
   */
  public saveToken(data: {
    token_type?: string;
    expires_in?: number;
    access_token?: string;
    refresh_token?: string;
  }, key: string = "jwtToken"): void {
    const nowTime: number = new Date().getTime();
    let {expires_in} = data;
    expires_in = expires_in === undefined ? 0 : expires_in;
    const tokenData = {
      ...data,
      // 将token过期秒数更新为过期时间戳 15天
      expires_in: expires_in * 1000 + nowTime,
      // refresh_token的过期时间戳 30天
      refresh_expires_in: expires_in * 1000 * 2 + nowTime,
    }
    const tokenString: string = JSON.stringify(tokenData);
    localStorage.setItem(key, tokenString);
  }
 
  /**
   * 获取TOKEN
   *
   * @param key
   */
  public getToken(key: string = "jwtToken"): {
    token_type: string;
    expires_in: number;
    access_token: string;
    refresh_expires_in: number;
    refresh_token: string;
  } {
    const token = localStorage.getItem(key);
    if (typeof token === "string") {
      const tokenJson: {
        token_type: string;
        expires_in: number;
        access_token: string;
        refresh_expires_in: number;
        refresh_token: string;
      } = JSON.parse(token);
      const {expires_in, refresh_expires_in} = tokenJson;
      return {
        ...tokenJson,
        expires_in: this.checkExpiresTime(expires_in) ? expires_in : 0,
        refresh_expires_in: this.checkExpiresTime(refresh_expires_in) ? refresh_expires_in : 0,
      };
    }
    return {
      token_type: "Bearer",
      expires_in: 0,
      access_token: "",
      refresh_expires_in: 0,
      refresh_token: "",
    };
  }
 
  /**
   * 验证TOKEN是否在有效期内
   *
   * @param time
   */
  public checkExpiresTime(time: number): boolean {
    const nowTime = new Date().getTime();
    return time > nowTime;
  }
 
  /**
   * 删除TOKEN
   *
   * @param key
   */
  public removeToken(key: string = "jwtToken"): void {
    localStorage.removeItem(key)
  }
}

ant.design pro => app.tsx

import {history, Link, request as requestApi} from 'umi';
import type {Context} from 'umi-request';
// token存储localstorage类
import Authority from "@/authority";
 
// 请求中间件
const requestMiddleware = async (ctx: Context, next: () => void) => {
  const {req} = ctx;
  const {url, options} = req;
  let {headers} = options;
 
  // 判断是否需要添加前缀,如果是统一添加可通过 prefix、suffix 参数配置
  if (url.indexOf('api') === 0) {
    ctx.req.url = `http://www.hf.name/${url}`;
  }
 
  // 基础header
  headers = {
    // 接受JSON数据
    'Accept': 'application/json',
    // 发送数据的数据类型
    'Content-Type': 'application/json',
    ...headers,
  };
 
  // 是否需要提供token,如果headers中有isGuest,代表无需token头
  if (headers && !headers.hasOwnProperty('isGuest')) {
    // 获取本地token
    const authority: Authority = new Authority();
    const jwtToken = authority.getToken();
    const {token_type, access_token, expires_in} = jwtToken;
    // 本地access token有效时
    if (expires_in > 0 && access_token.length > 0) {
      // 附加token
      headers = {
        Authorization: `${token_type} ${access_token}`,
        ...headers,
      };
    } else {
      // 本地access token过期时,验证refresh token是否有效
      const {refresh_expires_in, refresh_token} = jwtToken;
      if (refresh_expires_in > 0 && refresh_token.length > 0) {
        // refresh token有效,发送请求获取access token
        const refreshResponse = await requestApi('api/refresh-token', {
          method: 'POST',
          data: {refresh_token},
          headers: {isGuest: "true"},
        });
        // 刷新token的请求是否成功
        if (refreshResponse && refreshResponse.data !== undefined) {
          authority.saveToken(refreshResponse.data);
          // 附加新获取到的token继续发起原请求
          headers = {
            Authorization: `${refreshResponse.data.token_type} ${refreshResponse.data.access_token}`,
            ...headers,
          };
        } else {
          // refresh token未能换取到新的token时跳转登录页
          history.push(loginPath);
        }
      } else {
        // refresh token 无效时,跳转登录页
        history.push(loginPath);
      }
    }
  }
 
  // 更新头部
  ctx.req.options.headers = headers;
 
  await next();
};
 
export const request: RequestConfig = {
  middlewares: [requestMiddleware],
  // ant.design 需要的错误返回数据
  errorConfig: {
    adaptor: (resData) => {
      return {
        ...resData,
        success: !resData.hasOwnProperty('errors'),
        errorMessage: resData.message,
      };
    },
  },
};

————————————————

版权声明:本文为CSDN博主「QIHU.ZY」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/jncinets/article/details/120236048