React
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