axios:在单独的文件中使用 baseUrl 会导致在 axios 请求中设置身份验证令牌时出现问题 headers
Axios: Using baseUrl in a separate file causes problems with setting authentication token in axios request headers
我曾经在请求中这样写 API Url:
export const getAllAdmins2 = () => dispatch => {
axios
.get("http://baseUrl:3083/api/admin/getAllAdmins")
.then(retrievedAdmins => {
console.log("getAllAdmins2");
console.log(retrievedAdmins);
// this.setState({
// usersInformation: retrievedAdmins.data
// });
})
.catch(error => console.log(error));
};
但是,这可以通过在单独的文件中设置 URL 来改进:
conf/api.js
import axios from "axios";
export default axios.create({
baseURL: `http://baseUrl:3083`
});
所以我将 API 请求更改为:
import API from "../conf/api";
export const getAllAdmins = () => dispatch => {
API.get("api/admin/getAllAdmins")
.then(retrievedAdmins => {
console.log("retrievedAdmins insideAPI.get(api/admin/getAllAdmin)");
console.log(retrievedAdmins);
// this.setState({
// usersInformation: retrievedAdmins.data
// });
})
.catch(error => console.log(error));
};
但是,这导致了一个奇怪的问题:负责在每个请求中自动设置身份验证令牌的代码不再执行其工作。在后端,令牌是未定义:
2020-02-28T17:49:41+0100 <notice> TokenServices.js:76 Object.HasValidToken Access Token:undefined
这是负责设置 身份验证 header 的代码:
App.js
if (localStorage.jwtToken) {
// Set auth token header auth
setAuthToken(localStorage.jwtToken);
// Decode token and get user info and expiration
const decoded = jwt_decode(localStorage.jwtToken);
// Set User and is Authenticated
store.dispatch(setCurrentUser(decoded));
// Now if you reload a page, if the user has already logged-in you will still have his info in he state
// Check for expired token
const currentTime = Date.now() / 1000;
if (decoded.exp < currentTime) {
// Logout User
store.dispatch(logoutUser());
// Redirect to login
window.location.href = "/login";
}
}
utils/setAuthToken.js
// What we will do here will prevent us from manually making sure of having the token inside each relevant request
// If we're logged-in, we can call this function and it will always attach that authorization header
// TODO: Need to make sure that the token is stored inside x-access-token
import axios from "axios";
const setAuthToken = token => {
console.log("setAuthToken is called");
if (token) {
// Apply to every request
axios.defaults.headers.common = {
// Authorization: token,
//TODO: Not sure about this
"x-access-token": token
};
console.log("token is: ");
console.log(token);
console.log("axios.defaults.headers.common: ");
console.log(axios.defaults.headers.common);
} else {
// Delete the Auth header
axios.defaults.headers.common = {
//Authorization: token,
"x-access-token": token
};
}
};
export default setAuthToken;
这是 setAuthToken 的记录结果:
setAuthToken.js:7 setAuthToken is called
setAuthToken.js:15 token is:
setAuthToken.js:16 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwibm9tIjoiYXZlbXBhY2UiLCJlbWFpbCI6ImF2ZW1wYWNlQGF2ZW1wYWNlLmNvbSIsIm1vdF9kZV9wYXNzZSI6IlUyRnNkR1ZrWDEvRGdCN3JUUjB1YTJvc1BIcm1hRkswN3pjTGd5aSsxcE09IiwibGFzdF9sb2dpbiI6bnVsbCwicm9sZSI6InN1cGVyX3VzZXIiLCJjcmVhdGVkQXQiOiIyMDIwLTAyLTI4VDA5OjQwOjE4LjM3MFoiLCJ1cGRhdGVkQXQiOiIyMDIwLTAyLTI4VDA5OjQwOjE4LjM3MFoiLCJpYXQiOjE1ODI5MDg0NjAsImV4cCI6MTU4MjkxMjA2MH0.8Btk4f0Bdw-pM2qGEbk0s5V-u3jBugIHYDKH8aoDzW8
setAuthToken.js:17 axios.defaults.headers.common:
setAuthToken.js:18 {x-access-token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwib…A2MH0.8Btk4f0Bdw-pM2qGEbk0s5V-u3jBugIHYDKH8aoDzW8"}
它似乎有效。然而,正如我所说,在后端,当我使用 getAllAdmins 时,它使用 axios url 的新实现,token 是后端的 undefined
。但是,当我使用 getAllAdmins2 时,它使用 direct 实现 axios url,代码在后端很受欢迎,一切正常。
您的问题可能是因为 conf/api.js
中的 axios 实例是在您在 axios.defaults
中设置令牌之前创建的,因此您的实例不会受到影响。 IE。您的订单是:
- 创建不带令牌的 axios 实例(在 api.js 的 include/comiple 上完成)
- 加载令牌并设置默认值
因为你本质上有一个单例 axios 实例,你可以在加载令牌时设置它的默认值来代替全局默认值,即
之前:
// This is setting the defaults used when creating instance and the global axios is used
axios.defaults.headers.common = {
...
之后:
import API from "../conf/api";
...
// This will set the the defaults of your singleton instance
API.defaults.headers.common = {
...
以上应该可以解决您当前设置的问题,但另一种选择是返回使用全局 axios
(例如 axios.get
),而不是设置基础 URL在它的默认值上,即:
// During app init:
axios.defaults.baseURL = 'http://your.base.url';
我曾经在请求中这样写 API Url:
export const getAllAdmins2 = () => dispatch => {
axios
.get("http://baseUrl:3083/api/admin/getAllAdmins")
.then(retrievedAdmins => {
console.log("getAllAdmins2");
console.log(retrievedAdmins);
// this.setState({
// usersInformation: retrievedAdmins.data
// });
})
.catch(error => console.log(error));
};
但是,这可以通过在单独的文件中设置 URL 来改进:
conf/api.js
import axios from "axios";
export default axios.create({
baseURL: `http://baseUrl:3083`
});
所以我将 API 请求更改为:
import API from "../conf/api";
export const getAllAdmins = () => dispatch => {
API.get("api/admin/getAllAdmins")
.then(retrievedAdmins => {
console.log("retrievedAdmins insideAPI.get(api/admin/getAllAdmin)");
console.log(retrievedAdmins);
// this.setState({
// usersInformation: retrievedAdmins.data
// });
})
.catch(error => console.log(error));
};
但是,这导致了一个奇怪的问题:负责在每个请求中自动设置身份验证令牌的代码不再执行其工作。在后端,令牌是未定义:
2020-02-28T17:49:41+0100 <notice> TokenServices.js:76 Object.HasValidToken Access Token:undefined
这是负责设置 身份验证 header 的代码:
App.js
if (localStorage.jwtToken) {
// Set auth token header auth
setAuthToken(localStorage.jwtToken);
// Decode token and get user info and expiration
const decoded = jwt_decode(localStorage.jwtToken);
// Set User and is Authenticated
store.dispatch(setCurrentUser(decoded));
// Now if you reload a page, if the user has already logged-in you will still have his info in he state
// Check for expired token
const currentTime = Date.now() / 1000;
if (decoded.exp < currentTime) {
// Logout User
store.dispatch(logoutUser());
// Redirect to login
window.location.href = "/login";
}
}
utils/setAuthToken.js
// What we will do here will prevent us from manually making sure of having the token inside each relevant request
// If we're logged-in, we can call this function and it will always attach that authorization header
// TODO: Need to make sure that the token is stored inside x-access-token
import axios from "axios";
const setAuthToken = token => {
console.log("setAuthToken is called");
if (token) {
// Apply to every request
axios.defaults.headers.common = {
// Authorization: token,
//TODO: Not sure about this
"x-access-token": token
};
console.log("token is: ");
console.log(token);
console.log("axios.defaults.headers.common: ");
console.log(axios.defaults.headers.common);
} else {
// Delete the Auth header
axios.defaults.headers.common = {
//Authorization: token,
"x-access-token": token
};
}
};
export default setAuthToken;
这是 setAuthToken 的记录结果:
setAuthToken.js:7 setAuthToken is called
setAuthToken.js:15 token is:
setAuthToken.js:16 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwibm9tIjoiYXZlbXBhY2UiLCJlbWFpbCI6ImF2ZW1wYWNlQGF2ZW1wYWNlLmNvbSIsIm1vdF9kZV9wYXNzZSI6IlUyRnNkR1ZrWDEvRGdCN3JUUjB1YTJvc1BIcm1hRkswN3pjTGd5aSsxcE09IiwibGFzdF9sb2dpbiI6bnVsbCwicm9sZSI6InN1cGVyX3VzZXIiLCJjcmVhdGVkQXQiOiIyMDIwLTAyLTI4VDA5OjQwOjE4LjM3MFoiLCJ1cGRhdGVkQXQiOiIyMDIwLTAyLTI4VDA5OjQwOjE4LjM3MFoiLCJpYXQiOjE1ODI5MDg0NjAsImV4cCI6MTU4MjkxMjA2MH0.8Btk4f0Bdw-pM2qGEbk0s5V-u3jBugIHYDKH8aoDzW8
setAuthToken.js:17 axios.defaults.headers.common:
setAuthToken.js:18 {x-access-token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwib…A2MH0.8Btk4f0Bdw-pM2qGEbk0s5V-u3jBugIHYDKH8aoDzW8"}
它似乎有效。然而,正如我所说,在后端,当我使用 getAllAdmins 时,它使用 axios url 的新实现,token 是后端的 undefined
。但是,当我使用 getAllAdmins2 时,它使用 direct 实现 axios url,代码在后端很受欢迎,一切正常。
您的问题可能是因为 conf/api.js
中的 axios 实例是在您在 axios.defaults
中设置令牌之前创建的,因此您的实例不会受到影响。 IE。您的订单是:
- 创建不带令牌的 axios 实例(在 api.js 的 include/comiple 上完成)
- 加载令牌并设置默认值
因为你本质上有一个单例 axios 实例,你可以在加载令牌时设置它的默认值来代替全局默认值,即
之前:
// This is setting the defaults used when creating instance and the global axios is used
axios.defaults.headers.common = {
...
之后:
import API from "../conf/api";
...
// This will set the the defaults of your singleton instance
API.defaults.headers.common = {
...
以上应该可以解决您当前设置的问题,但另一种选择是返回使用全局 axios
(例如 axios.get
),而不是设置基础 URL在它的默认值上,即:
// During app init:
axios.defaults.baseURL = 'http://your.base.url';