大家好,
我创建了一个用于受保护 api 资源的 axios 新实例,并在其上附加了带有令牌的 auth 标头,但问题是如果我转到控制台并从 localStorage 中删除令牌,axios 仍将其作为实例发送没有更新。
是否有解决方案,以便实例中的身份验证标头可以在每个请求中检查 localStorage 中的令牌?
谢谢!
我有一个类似的用例,如果每个请求都懒惰地评估传递的标头,那就太好了。
想法:
与其急切地将标头散列作为对象( axios.create({headers: {...}})
传递,我们可以传递一个返回标头( axios.create({headers: () => {...}}
)的函数,该函数将在发送请求之前进行评估。
你怎么认为?
编辑:这是一个提议,我认为目前这行不通。
我遇到了同样的用例。 我在短期内最终做的是使用transformRequest
函数。 绝对是一个黑客,很乐意帮助在代码库中实施适当的延迟加载方法。
请参阅下面的代码片段。 auth()
获取登录用户的令牌(如果可用)。
let HTTP = axios.create({
baseURL: baseurl,
transformRequest: [function (data, headers) {
headers['Authorization'] = auth()
return JSON.stringify(data)
}],
headers: {
'Content-Type': 'application/json'
}
})
为此,我使用了拦截器。 如果请求的基本 URL 是我的 API,我会添加 auth 标头(以防止将凭据发送给第三方)。 这是在每个请求上运行的,因此如果令牌更改(例如由于令牌刷新),则下一个请求将获取新令牌。 我还确保我检查请求中的现有值,以允许覆盖来自调用站点的标头,如果由于某种原因发生这种情况是必要的。
axios.interceptors.request.use(
config => {
if (config.baseURL === baseApiAddress && !config.headers.Authorization) {
const token = getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
}
return config;
},
error => Promise.reject(error)
);
@mattstrayer你能告诉我
我结束了这个。
axios.create({
baseURL: '<your-api>',
headers: {
Authorization: {
toString () {
return `Bearer ${localStorage.getItem('token')}`
}
}
}
})
我不确定它是否适用于任何情况。
我的http.js
文件:
import axios from 'axios';
import {store} from './store';
const http = axios.create ({
baseURL: process.env.VUE_APP_ROOT_API,
timeout: 1000,
headers: {'Content-Type': 'application/json'},
});
http.interceptors.request.use (
function (config) {
const token = store.token;
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
},
function (error) {
return Promise.reject (error);
}
);
export default http;
我的商店,一个简单的获取/设置“类”
export const store = {
_username: '',
_email: '',
_token: '',
isLogged () {
return this.token
},
set username (str) {
this._username = str
localStorage.setItem('username',str)
},
get username () {
return this._username || localStorage.getItem('username')
},
set email (str) {
this._email = str
localStorage.setItem('email',str)
},
get email () {
return this._email || localStorage.getItem('email')
},
set token (str) {
this._token = str
localStorage.setItem('token',str)
},
get token () {
return this._token || localStorage.getItem('token')
}
}
我的用户服务“类”:
import http from './http'
export const user = {
ping: () => http.get('/users/ping'),
save: (user) => http.post('/users', user)
}
最后,我的实现:
import {user} from '@/services'
user.ping().then( r => {
console.log(r.data)
})
顺便说一句,
process.env.VUE_APP_ROOT_API
和@/services
是 Vue 的东西......
结果:
@danielschmitz谢谢你的例子!!
看起来你们都想通了,这不是错误,所以我要关闭它了🙂
我发现将拦截器包装在 async/await 中以确保在触发 API 调用之前设置我的令牌很有用:
http.interceptors.request.use (
async (config) => {
const token = await getToken(); // slightly longer running function than example above
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
},
(error) => {
return Promise.reject (error);
}
);
为此,我使用了拦截器。 如果请求的基本 URL 是我的 API,我会添加 auth 标头(以防止将凭据发送给第三方)。 这是在每个请求上运行的,因此如果令牌更改(例如由于令牌刷新),则下一个请求将获取新令牌。 我还确保我检查请求中的现有值,以允许覆盖来自调用站点的标头,如果由于某种原因发生这种情况是必要的。
axios.interceptors.request.use( config => { if (config.baseURL === baseApiAddress && !config.headers.Authorization) { const token = getToken(); if (token) { config.headers.Authorization = `Bearer ${token}`; } } return config; }, error => Promise.reject(error) );
拦截器似乎是最优雅的解决方案
最有用的评论
为此,我使用了拦截器。 如果请求的基本 URL 是我的 API,我会添加 auth 标头(以防止将凭据发送给第三方)。 这是在每个请求上运行的,因此如果令牌更改(例如由于令牌刷新),则下一个请求将获取新令牌。 我还确保我检查请求中的现有值,以允许覆盖来自调用站点的标头,如果由于某种原因发生这种情况是必要的。