Ola pessoal,
Fiz uma nova instância do axios que uso para os recursos api protegidos e anexei o cabeçalho auth com token a ele, mas o problema é se eu for ao console e excluir o tokem de localStorage, axios ainda está enviando-o como a instância não foi atualizado.
Existe uma solução para que meus cabeçalhos de autenticação na instância possam verificar o token em localStorage em cada solicitação?
Obrigado!
Eu tenho um caso de uso semelhante em que seria ótimo se os cabeçalhos passados fossem avaliados lentamente para cada solicitação.
Pensamento:
Em vez de passar o hash dos cabeçalhos avidamente como um objeto ( axios.create({headers: {...}})
, poderíamos passar uma função que retorna os cabeçalhos ( axios.create({headers: () => {...}}
) que seriam avaliados antes do envio da solicitação.
O que você acha?
Edit: Esta é uma proposta, não acho que funcione no momento.
Corri para o mesmo caso de uso. O que acabei fazendo em curto prazo foi usar a função transformRequest
. Definitivamente um hack e adoraria ajudar na implementação de uma abordagem de carregamento lento adequado na base de código.
Veja abaixo o trecho de código. auth()
obtém o token do usuário conectado, se disponível.
let HTTP = axios.create({
baseURL: baseurl,
transformRequest: [function (data, headers) {
headers['Authorization'] = auth()
return JSON.stringify(data)
}],
headers: {
'Content-Type': 'application/json'
}
})
Usei interceptores para esse propósito. Se a URL base da solicitação for para minha API, adiciono o cabeçalho de autenticação (para evitar o envio de credenciais a terceiros). Isso é executado em cada solicitação, portanto, se o token mudar (por exemplo, como resultado de uma atualização de token), a próxima solicitação seleciona o novo token. Também garanto que verifico os valores existentes na solicitação para permitir a substituição do cabeçalho do site da chamada se isso for necessário por qualquer motivo.
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 você pode me mostrar o método getToken ()? Você armazena seu token em localStorage ou AsyncStorage (React Native)? Desde já, obrigado!
Eu acabei com isso.
axios.create({
baseURL: '<your-api>',
headers: {
Authorization: {
toString () {
return `Bearer ${localStorage.getItem('token')}`
}
}
}
})
Não tenho certeza se funciona para qualquer caso.
Meu arquivo 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;
Minha loja, uma simples "classe" get / set
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')
}
}
Minha "classe" de serviço de usuário:
import http from './http'
export const user = {
ping: () => http.get('/users/ping'),
save: (user) => http.post('/users', user)
}
e finalmente, minha implementação:
import {user} from '@/services'
user.ping().then( r => {
console.log(r.data)
})
aliás,
process.env.VUE_APP_ROOT_API
e@/services
são coisas Vue ...
Resultado:
@danielschmitz obrigado por esse exemplo !!
Parece que vocês perceberam isso e não é um bug, então estou encerrando isso 🙂
Achei útil envolver o interceptor em async / await para garantir que meu token fosse definido antes que a chamada de API fosse acionada:
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);
}
);
Usei interceptores para esse propósito. Se a URL base da solicitação for para minha API, adiciono o cabeçalho de autenticação (para evitar o envio de credenciais a terceiros). Isso é executado em cada solicitação, portanto, se o token mudar (por exemplo, como resultado de uma atualização de token), a próxima solicitação seleciona o novo token. Também garanto que verifico os valores existentes na solicitação para permitir a substituição do cabeçalho do site da chamada se isso for necessário por qualquer motivo.
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) );
Interceptor parece a solução mais elegante
Comentários muito úteis
Usei interceptores para esse propósito. Se a URL base da solicitação for para minha API, adiciono o cabeçalho de autenticação (para evitar o envio de credenciais a terceiros). Isso é executado em cada solicitação, portanto, se o token mudar (por exemplo, como resultado de uma atualização de token), a próxima solicitação seleciona o novo token. Também garanto que verifico os valores existentes na solicitação para permitir a substituição do cabeçalho do site da chamada se isso for necessário por qualquer motivo.