chatGPT deBug解决管理员登入,服务器返回401,没有拿到数据

问题复现:

连接钱包后,会调用函数,弹出窗口让用户签名

   if (signatureMessage) {
        await signMessageAsync({
          message: signatureMessage,
        });
        dispatch(changeHasLoggedToTrue());
      }

有了签名后,会调用signIn来设置本地存储

signIn函数

javascript">  const signIn = async (signature) => {
    try {
      const signinRes = await API.post(`/auth/signin`, {
        address: address,
        signature: signature,
      });

      const a***essToken = signinRes.data?.data?.a***ess_token;
      setLocalStorage("a***essToken", a***essToken);//设置本地存储
      refreshAPIToken();
      addressInfo.current.address = address;
    } catch (err) {
      console.log("signin");
      showMessage({
        type: "error",
        title: "Failed to sign-in",
        body: err.message,
      });
      disconnect();
    }
  };

如果用户连接了钱包就会调接口,获取用户是否是管理员 通过RTK(redux toolkit)存储在isAdmin变量里

 const res = await API.get(`/member/${address}`);
        if (!res.data.data) {
          dispatch(changeIsAdminToFalse());
          return;
        }
        if (res.data.data.role.includes("Member")) {
          dispatch(changeIsMemberToTrue());
        }

当isAdmin为true的时候,才显示member列表

后端接口也限制了,不是管理员拿不到数据,而我明明用管理员登入了,还是拿不到,刷新才拿得到数据。不刷新的时候控制台报401,Unauthorized,没有权限。

解决过程

于是问了gpt

gpt给了5种可能的原因

关键是第一条 问题定位到了没有a***essToken 但是我一看控制台Application里面 a***ess token没错,是有的,但是数据要刷新页面才出来,于是我继续问

我:the a***ess token is right , we can get the requested source by this token after refresh. But how to get the requested source without refresh

GPT:If you’re able to a***ess the resource after refreshing the page, it’s possible that the a***ess token is not being sent with subsequent requests after the initial connection is made.

To ensure that the a***ess token is being sent with all subsequent requests, you can set the token in the headers of the Axios instance. Here’s an example of how to do this:
翻譯:刷新后才出现数据,可能是因为在发送请求的时候a***ess token没有被发送,为了确保所有的请求都带有a***ess token 需要给axios实例设置header

import axios from 'axios';

const API = axios.create({
  baseURL: 'https://example.***/api',
  headers: {
    Authorization: `Bearer ${getLocalStorage('a***essToken')}`,
  },
});

API.interceptors.response.use(
  response => response,
  async error => {
    const originalRequest = error.config;
    if (error.response.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      const a***essToken = await handleRefreshToken();
      API.defaults.headers.***mon.Authorization = `Bearer ${a***essToken}`;
      return API(originalRequest);
    }
    return Promise.reject(error);
  },
);

GPT给了一段代码 我自己再看逻辑 修改 关键就是当服务器返回401的时候,要给axios请求设置a***essToken,再次发送请求;

但是这种有漏洞,

1.每次请求刚开始都返回401,request拦截之后,再次发送请求才拿到数据

2.如果a***essToken过期了,请求不到数据,需求是要清除本地缓存并退出钱包登录

第2条是新增的需求,如何判断a***essToken过期,GPT说如果a***essToken过期,服务器会返回401,所以这里if判断服务器会返回401后的逻辑不能是重新发送请求。首先要解决第一个问题。为何每次请求都返回401?

打log,发现在连接钱包set token,token有值之前,就发送请求,所以要在连接钱包set token,确保token有值之后才发送请求,之前是判断为管理员就发送请求,这个在需求层面来将没错,但是connect wallet 设置isAdmin为true的时候还没有set token 所以在 set token之后新增 dispatch(changeSigninToTrue()); useEffect监听hasSiginin:

  useEffect(() => {
    if (hasSiginin) {
      console.log("有發送請求");
      searchList();
    }
  }, []);

最终代码:

import axios from "axios";
import { getLocalStorage, removeLocalStorage } from "@/src/utils/utility";
import { useLogout } from "../src/hooks/useLogout";

const API = axios.create({
  baseURL: process.env.NEXT_PUBLIC_FRENART_BACKEND_API,
});

API.interceptors.request.use(
  (config) => {
    const a***essToken = refreshAPIToken();
    if (a***essToken) {
      config.headers.Authorization = `Bearer ${a***essToken}`; //a***essToken
    }
    return config;
  },
  (error) => Promise.reject(error)
);

function handleUnauthorizedError() {
  const logout = useLogout();
  logout();
}

API.interceptors.response.use(
  (response) => response,
  async (error) => {
    const a***essToken = refreshAPIToken();
    error.config.headers.Authorization = `Bearer ${a***essToken}`;
    const originalRequest = error.config;

    if (error.response?.status === 401 && !originalRequest._retry) {
      console.log("401");
      handleUnauthorizedError();
    }
    return Promise.reject(error);
  }
);

function refreshAPIToken() {
  const a***essToken = getLocalStorage("a***essToken");
  API.defaults.headers.***mon.Authorization = `Bearer ${a***essToken}`;
  return a***essToken;
}

export { refreshAPIToken };
export default API;

之后管理员连接钱包,就能拿到数据了,因为发送请求的时候 header里面有了Authorization,即有了a***essToken

转载请说明出处内容投诉
CSS教程_站长资源网 » chatGPT deBug解决管理员登入,服务器返回401,没有拿到数据

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买