Axios 实例在第一次调用时未从本地存储获取令牌 - React js + django
Axios instance not getting the token from local storage on first call - React js + django
我创建了一个 Axios 实例来设置 baseURL 和 headers。 header 还需要包含授权令牌。因此,当用户登录时,我调用 API 来使用 useEffect 获取与用户相关的一些数据。因此 API 在登录完成后立即被调用。此 API 需要权限,因此需要令牌。登录时,我将令牌存储在本地存储中,但由于某种原因,在第一次调用实例时未加载令牌,我从后端收到 Unauthorised 错误。但是如果我手动重新加载页面,API 会再次被调用,但这次实例会收到令牌并获取数据。下面是我的代码。
axios 实例
const baseURL = "http://127.0.0.1:8000";
// getting the token from the localstorage
let authTokens = localStorage.getItem("token")
? JSON.parse(localStorage.getItem("token"))
: null;
const axiosInstance = axios.create({
baseURL,
headers: { Authorization: `Bearer ${authTokens?.access}` },
});
api 来电
export const fetchTeacherDetail = async () => {
try {
let response = await axiosInstance.get(`/teacher/get-detail/`);
return response;
} catch (error) {
ToastNotification(
"We are facing some errors. Please trying again later.",
"error"
);
}
};
我看了一个 youtube 视频来了解这个,他没有收到这个错误,但由于某种原因我收到了这个错误。请给我建议我该怎么做。
更新
用于显示我在本地存储中存储令牌的位置的代码
在 redux 中存储令牌和用户详细信息的操作
export const loginUser = (email, password) => async (dispatch) => {
try {
// before calling the api
dispatch(loginPending());
//calling the api
const response = await userLogin(email, password);
if (response.status !== 200) {
return dispatch(loginFail(response.status));
} else {
dispatch(loginSuccess(response.data));
}
} catch (error) {
dispatch(loginFail(error.message));
}
};
userLogin() API 代码
export const userLogin = async (email, password) => {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify({ email, password });
try {
const response = await axios.post(`${url}/token/`, body, config);
if (response.status === 200) {
localStorage.setItem("token", JSON.stringify(response.data));
return response;
}
} catch (error) {
ToastNotification("Credentials provided are not valid", "error");
}
};
response.data 在上述函数中收到的模拟值
refresh: 'eyJ0eXAiOiJKV1QUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTY1ODU4NTUxMSwiaWF0IjoxNjUwODA5NTExLCJqdGkiOiI4NDRjZWFjNTFkOWI0OGNkOWE0MTFlYzU4ZWY4ZDMxYiIsInVzZXJfaWQiOiI0YjdhODEzYmFkYi05VzZXIiOmZhbHNlLCJpc19zdGFmZiI6ZmFsc2V9.zlGb4tPtJ9HlUvSUZW6QrHHfDsUU8hZ6rliYc3RbJXQ',
access: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjU4NTg1NTExLCJpYXQiOjEk1MTEsImp0aSI6ImEyYzg1NzAyZmY0ZjQ4YmRiZjEwZjEzNTUwYjk0MzE2IiwidXNlcl9pZCI6lciI6dHJ1Zsc2UsImlzX3N1cGVydXNlciI6ZmFsc2UsImlzX3N0YWZmIjpmYWxzZX0.qrictVbES22dGpA0dpVA5KLTZkrMsCM0hDHq2Yrs
您的问题可能是因为您在应用程序启动时设置了 axios 实例令牌,但从未在登录时更新它。
您需要在登录时通过再次检查 localStorage 数据来“刷新”该值。
一个快速的解决方案是每次调用 API
时计算 headers
const baseURL = "http://127.0.0.1:8000";
export const getToken = () => localStorage.getItem("token")
? JSON.parse(localStorage.getItem("token"))
: null;
export const getAuthorizationHeader = () => `Bearer ${getToken()}`;
export const axiosInstance = axios.create({
baseURL,
headers: { Authorization: getAuthorizationHeader() },
});
然后在API调用
export const fetchSomething = async () => {
try {
const response = await axiosInstance.get("/foo", {
headers: { Authorization: getAuthorizationHeader() }
});
return response;
} catch (error) {
// error handling
}
};
另一种解决方案是在登录时通过执行类似这样的操作来改变 axios 实例
axiosInstance.defaults.headers.Authorization = `Bearer ${result.access}`
我相信问题不在后端,因为您需要手动刷新以使授权正常,所以无需担心后端问题是什么,您正在将令牌的值存储在 const getToken
它将永远存储在那里,我的意思是,如果它在开始时将它作为坏令牌或 null 获取,它将始终是相同的初始值,所以你要做的是:
const baseURL = "http://127.0.0.1:8000";
const axiosInstance = axios.create({
baseURL,
headers: {
Authorization: `Bearer ${
localStorage.getItem("token")
? JSON.parse(localStorage.getItem("token")).access
: null
}`,
}
});
我创建了一个 Axios 实例来设置 baseURL 和 headers。 header 还需要包含授权令牌。因此,当用户登录时,我调用 API 来使用 useEffect 获取与用户相关的一些数据。因此 API 在登录完成后立即被调用。此 API 需要权限,因此需要令牌。登录时,我将令牌存储在本地存储中,但由于某种原因,在第一次调用实例时未加载令牌,我从后端收到 Unauthorised 错误。但是如果我手动重新加载页面,API 会再次被调用,但这次实例会收到令牌并获取数据。下面是我的代码。
axios 实例
const baseURL = "http://127.0.0.1:8000";
// getting the token from the localstorage
let authTokens = localStorage.getItem("token")
? JSON.parse(localStorage.getItem("token"))
: null;
const axiosInstance = axios.create({
baseURL,
headers: { Authorization: `Bearer ${authTokens?.access}` },
});
api 来电
export const fetchTeacherDetail = async () => {
try {
let response = await axiosInstance.get(`/teacher/get-detail/`);
return response;
} catch (error) {
ToastNotification(
"We are facing some errors. Please trying again later.",
"error"
);
}
};
我看了一个 youtube 视频来了解这个,他没有收到这个错误,但由于某种原因我收到了这个错误。请给我建议我该怎么做。
更新
用于显示我在本地存储中存储令牌的位置的代码
在 redux 中存储令牌和用户详细信息的操作
export const loginUser = (email, password) => async (dispatch) => {
try {
// before calling the api
dispatch(loginPending());
//calling the api
const response = await userLogin(email, password);
if (response.status !== 200) {
return dispatch(loginFail(response.status));
} else {
dispatch(loginSuccess(response.data));
}
} catch (error) {
dispatch(loginFail(error.message));
}
};
userLogin() API 代码
export const userLogin = async (email, password) => {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify({ email, password });
try {
const response = await axios.post(`${url}/token/`, body, config);
if (response.status === 200) {
localStorage.setItem("token", JSON.stringify(response.data));
return response;
}
} catch (error) {
ToastNotification("Credentials provided are not valid", "error");
}
};
response.data 在上述函数中收到的模拟值
refresh: 'eyJ0eXAiOiJKV1QUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTY1ODU4NTUxMSwiaWF0IjoxNjUwODA5NTExLCJqdGkiOiI4NDRjZWFjNTFkOWI0OGNkOWE0MTFlYzU4ZWY4ZDMxYiIsInVzZXJfaWQiOiI0YjdhODEzYmFkYi05VzZXIiOmZhbHNlLCJpc19zdGFmZiI6ZmFsc2V9.zlGb4tPtJ9HlUvSUZW6QrHHfDsUU8hZ6rliYc3RbJXQ',
access: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjU4NTg1NTExLCJpYXQiOjEk1MTEsImp0aSI6ImEyYzg1NzAyZmY0ZjQ4YmRiZjEwZjEzNTUwYjk0MzE2IiwidXNlcl9pZCI6lciI6dHJ1Zsc2UsImlzX3N1cGVydXNlciI6ZmFsc2UsImlzX3N0YWZmIjpmYWxzZX0.qrictVbES22dGpA0dpVA5KLTZkrMsCM0hDHq2Yrs
您的问题可能是因为您在应用程序启动时设置了 axios 实例令牌,但从未在登录时更新它。
您需要在登录时通过再次检查 localStorage 数据来“刷新”该值。
一个快速的解决方案是每次调用 API
时计算 headersconst baseURL = "http://127.0.0.1:8000";
export const getToken = () => localStorage.getItem("token")
? JSON.parse(localStorage.getItem("token"))
: null;
export const getAuthorizationHeader = () => `Bearer ${getToken()}`;
export const axiosInstance = axios.create({
baseURL,
headers: { Authorization: getAuthorizationHeader() },
});
然后在API调用
export const fetchSomething = async () => {
try {
const response = await axiosInstance.get("/foo", {
headers: { Authorization: getAuthorizationHeader() }
});
return response;
} catch (error) {
// error handling
}
};
另一种解决方案是在登录时通过执行类似这样的操作来改变 axios 实例
axiosInstance.defaults.headers.Authorization = `Bearer ${result.access}`
我相信问题不在后端,因为您需要手动刷新以使授权正常,所以无需担心后端问题是什么,您正在将令牌的值存储在 const getToken
它将永远存储在那里,我的意思是,如果它在开始时将它作为坏令牌或 null 获取,它将始终是相同的初始值,所以你要做的是:
const baseURL = "http://127.0.0.1:8000";
const axiosInstance = axios.create({
baseURL,
headers: {
Authorization: `Bearer ${
localStorage.getItem("token")
? JSON.parse(localStorage.getItem("token")).access
: null
}`,
}
});