Axios: Atualizando cabeçalhos de autenticação em cada solicitação?

Criado em 25 fev. 2018  ·  10Comentários  ·  Fonte: axios/axios

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!

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.

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)
);

Todos 10 comentários

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:
image

@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

Esta página foi útil?
0 / 5 - 0 avaliações