如何在axios中刷新token?

问题描述 投票:0回答:2

我的问题与

customAxios.interceptors.response.use
有关。我来这里的目的是;如果令牌过期并且出现 401 错误,请在出现 401 错误时再次发出请求,并将新令牌写入标头。另一方面,如果我收到除 401 错误之外的错误,请显示
error.response.data
。你认为这个逻辑设置正确吗?我尝试测试,但我不确定,尤其是 401 错误情况

import axios from "axios";
import { LoginAPI } from "../playwright/tests/login/login.api";
import { test } from "@playwright/test"
import {configEnv} from "../config/config"

test.beforeAll(async () => {
    await LoginAPI.API.Signin.run()
});
const customAxios = axios.create({
    baseURL: configEnv.apiBaseURL
});

customAxios.interceptors.request.use(
    async (config) => {
        if (config.headers) {
            config.headers['Authorization'] = `Bearer ${LoginAPI.States.token}`;
            return config;
        }
        return config;
    },
    (error) => {
        Promise.reject(error);
    }
);

customAxios.interceptors.response.use(
    function(response) {
      return response;
    },
   async function(error) {
      if (401 === error.response.status) {
        await LoginAPI.API.Signin.run()
        customAxios.defaults.headers.common['Authorization'] = `Bearer ${LoginAPI.States.token}`
      } else {
        return Promise.reject(error.response.data);
      }
    }
  );

export default customAxios
javascript reactjs typescript axios playwright
2个回答
5
投票

我建议您将令牌存储在 localStorage 中,然后在刷新后替换它。这样您就可以在 API 类中的一个位置设置令牌。

import axios from "axios";

export const ApiClient = () => {
    // Create a new axios instance
    const api = axios.create({
        baseURL: "URL",
        headers: {
            "Content-Type": "application/json",
            Accept: "application/json",
        },
    });

    // Add a request interceptor to add the JWT token to the authorization header
    api.interceptors.request.use(
        (config) => {
            const token = sessionStorage.getItem("jwtToken");
            if (token) {
                config.headers.Authorization = `Bearer ${token}`;
            }
            return config;
        },
        (error) => Promise.reject(error)
    );

    // Add a response interceptor to refresh the JWT token if it's expired
    api.interceptors.response.use(
        (response) => response,
        (error) => {
            const originalRequest = error.config;

            // If the error is a 401 and we have a refresh token, refresh the JWT token
            if (
                error.response.status === 401 &&
                sessionStorage.getItem("refreshToken")
            ) {
                const refreshToken = sessionStorage.getItem("refreshToken");

                let data = JSON.stringify({
                    refresh_token: refreshToken,
                });

                post("/refreshToken", data)
                    .then((response) => {
                        sessionStorage.setItem("jwtToken", response.token);
                        sessionStorage.setItem("refreshToken", response.refresh_token);

                        // Re-run the original request that was intercepted
                        originalRequest.headers.Authorization = `Bearer ${response.token}`;
                        api(originalRequest)
                            .then((response) => {
                                return response.data;
                            })
                            .catch((error) => {
                                console.log(error);
                            });
                        // return api(originalRequest)
                    })
                    .catch((err) => {
                        // If there is an error refreshing the token, log out the user
                        console.log(err);
                    });
            }

            // Return the original error if we can't handle it
            return Promise.reject(error);
        }
    );

    const login = (email, password) => {
        return api
            .post("/authentication_token", { email, password })
            .then(({ data }) => {
                // Store the JWT and refresh tokens in session storage
                sessionStorage.setItem("jwtToken", data.token);
                sessionStorage.setItem("refreshToken", data.refresh_token);
            })
            .catch((err) => {
                // Return the error if the request fails
                return err;
            });
    };


    const get = (path) => {
        return api.get(path).then((response) => response.data);
    };

    const post = (path, data) => {
        return api.post(path, data).then((response) => response.data);
    };

    const put = (path, data) => {
        return api.put(path, data).then((response) => response.data);
    };

    const del = (path) => {
        return api.delete(path).then((response) => response);
    };



    return {
        login,
        get,
        post,
        put,
        del,
    };
};

最好的, 克里斯


0
投票

这是从 @cLx 的版本修改而来的另一个版本。它周围没有包装的 ApiClient,并且它可以防止触发多个 /refresh-token 调用。此示例中的一个烦恼是我基本上使用两个术语来表示“access_token”。它在存储中的关键是“令牌”,但作为整个代码中的变量,它被称为

access_token

import axios from 'axios';

const axiosInstance = axios.create({
    baseURL: process.env.REACT_APP_API_BASE_URL,
    headers: {
        "Content-Type": "application/json",
        Accept: "application/json",
    },
});

const refreshTheToken = async (data) => {
     await axiosInstance.post("/refresh_token", data)
        .then((response) => {
            const access_token = JSON.stringify(response.data.access_token);
            const refresh_token = JSON.stringify(response.data.refresh_token);
            sessionStorage.setItem("token", access_token);
            sessionStorage.setItem("refresh_token", refresh_token);
            return access_token;
        })
        .catch((err) => {
            // If there is an error refreshing the token, log out the user
            console.log(err);
            return Promise.reject(err);
        });
}
// Add a request interceptor to add the JWT token to the authorization header
axiosInstance.interceptors.request.use(
    (config) => {
        const token = JSON.parse(sessionStorage.getItem("token"));
        if (token) {
            config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
    },
    (error) => Promise.reject(error)
);

// Add a response interceptor to refresh the JWT token if it's expired
axiosInstance.interceptors.response.use(
    (response) => {
        return response
    },
    async (error) => {
        const originalRequest = error.config;

        // If the error is a 401 and we have a refresh token, refresh the JWT token
        if (error.response.status === 401 && sessionStorage.getItem("refresh_token")) {
            const refreshToken = JSON.parse(sessionStorage.getItem("refresh_token"));

            let data = JSON.stringify({
                refresh_token: refreshToken,
            });

            const access_token = await refreshTheToken(data)
            // Re-run the original request that was intercepted
            originalRequest.headers.Authorization = `Bearer ${access_token}`;
            return axiosInstance(originalRequest);
        }

        // Return the original error if we can't handle it
        return Promise.reject(error);
    }
);


export default axiosInstance;
© www.soinside.com 2019 - 2024. All rights reserved.