328 votes

Attacher l'en-tête d'autorisation pour toutes les demandes axios

J'ai une application react/redux qui récupère un jeton depuis un serveur api. Après l'authentification de l'utilisateur, j'aimerais que toutes les demandes axios aient ce jeton comme en-tête d'autorisation sans avoir à le joindre manuellement à chaque demande dans l'action. Je suis assez nouveau dans react/redux et je ne suis pas sûr de la meilleure approche et je ne trouve pas de résultats de qualité sur Google.

Voici mon installation redux :

// actions.js
import axios from 'axios';

export function loginUser(props) {
  const url = `https://api.mydomain.com/login/`;
  const { email, password } = props;
  const request = axios.post(url, { email, password });

  return {
    type: LOGIN_USER,
    payload: request
  };
}

export function fetchPages() {
  /* here is where I'd like the header to be attached automatically if the user
     has logged in */ 
  const request = axios.get(PAGES_URL);

  return {
    type: FETCH_PAGES,
    payload: request
  };
}

// reducers.js
const initialState = {
  isAuthenticated: false,
  token: null
};

export default (state = initialState, action) => {
  switch(action.type) {
    case LOGIN_USER:
      // here is where I believe I should be attaching the header to all axios requests.
      return {
        token: action.payload.data.key,
        isAuthenticated: true
      };
    case LOGOUT_USER:
      // i would remove the header from all axios requests here.
      return initialState;
    default:
      return state;
  }
}

Mon jeton est stocké dans redux store sous state.session.token .

Je suis un peu perdu sur la façon de procéder. J'ai essayé de faire un instance d'axios dans un fichier de mon répertoire racine et de le mettre à jour/importer au lieu de le faire à partir de node_modules, mais il ne joint pas l'en-tête lorsque l'état change. Tout commentaire ou idée est le bienvenu, merci.

0 votes

Où stockez-vous le jeton d'autorisation après qu'il ait été reçu du serveur ? localStorage ?

0 votes

Dans le magasin redux session.token

490voto

Hardik Modha Points 4462

Il existe plusieurs façons d'y parvenir. J'ai expliqué ici les deux approches les plus courantes.

1. Vous pouvez utiliser intercepteurs axios pour intercepter toutes les demandes et ajouter des en-têtes d'autorisation.

// Add a request interceptor
axios.interceptors.request.use(function (config) {
    const token = store.getState().session.token;
    config.headers.Authorization =  token;

    return config;
});

2. De la documentation de axios vous pouvez voir qu'il y a un mécanisme disponible qui vous permet de définir l'en-tête par défaut qui sera envoyé avec chaque demande que vous faites.

axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;

Donc dans votre cas :

axios.defaults.headers.common['Authorization'] = store.getState().session.token;

Si vous le souhaitez, vous pouvez créer une fonction auto-exécutable qui définira elle-même l'en-tête d'autorisation lorsque le jeton est présent dans le magasin.

(function() {
     String token = store.getState().session.token;
     if (token) {
         axios.defaults.headers.common['Authorization'] = token;
     } else {
         axios.defaults.headers.common['Authorization'] = null;
         /*if setting null does not remove `Authorization` header then try     
           delete axios.defaults.headers.common['Authorization'];
         */
     }
})();

Désormais, vous n'avez plus besoin de joindre manuellement un jeton à chaque demande. Vous pouvez placer la fonction ci-dessus dans le fichier dont l'exécution est garantie à chaque fois ( par exemple Fichier qui contient les routes).

J'espère que cela vous aidera :)

1 votes

J'utilise déjà redux-persist mais je vais regarder le middleware pour attacher le jeton dans l'en-tête, merci !

4 votes

@awwester Vous n'avez pas besoin de middleware pour joindre le jeton dans l'en-tête. Attacher le jeton dans l'en-tête est axios.defaults.header.common[Auth_Token] = token aussi simple que cela.

4 votes

@HardikModha Je suis curieux de savoir comment on pourrait faire cela avec l'API Fetch.

125voto

llioor Points 64

Si vous utilisez la version "axios" : "^0.17.1" version vous pouvez faire comme ceci :

Créer une instance de axios :

// Default config options
  const defaultOptions = {
    baseURL: <CHANGE-TO-URL>,
    headers: {
      'Content-Type': 'application/json',
    },
  };

  // Create instance
  let instance = axios.create(defaultOptions);

  // Set the AUTH token for any request
  instance.interceptors.request.use(function (config) {
    const token = localStorage.getItem('token');
    config.headers.Authorization =  token ? `Bearer ${token}` : '';
    return config;
  });

Ensuite, pour toute demande, le jeton sera sélectionné à partir de localStorage et sera ajouté aux en-têtes de la demande.

J'utilise la même instance dans toute l'application avec ce code :

import axios from 'axios';

const fetchClient = () => {
  const defaultOptions = {
    baseURL: process.env.REACT_APP_API_PATH,
    method: 'get',
    headers: {
      'Content-Type': 'application/json',
    },
  };

  // Create instance
  let instance = axios.create(defaultOptions);

  // Set the AUTH token for any request
  instance.interceptors.request.use(function (config) {
    const token = localStorage.getItem('token');
    config.headers.Authorization =  token ? `Bearer ${token}` : '';
    return config;
  });

  return instance;
};

export default fetchClient();

Bonne chance.

0 votes

@NguyenPhúc Avec plaisir, le but est d'utiliser des "intercepteurs" d'axios.

1 votes

C'est la meilleure réponse... pour initialiser le jeton sur les intercepteurs pour chaque requête ! . Merci

1 votes

Vous ne devez jamais stocker le jeton dans localStorage

53voto

Kmaschta Points 1099

La meilleure solution consiste à créer un service client que vous instanciez avec votre jeton et à l'utiliser pour envelopper les données de l'utilisateur. axios .

import axios from 'axios';

const client = (token = null) => {
    const defaultOptions = {
        headers: {
            Authorization: token ? `Token ${token}` : '',
        },
    };

    return {
        get: (url, options = {}) => axios.get(url, { ...defaultOptions, ...options }),
        post: (url, data, options = {}) => axios.post(url, data, { ...defaultOptions, ...options }),
        put: (url, data, options = {}) => axios.put(url, data, { ...defaultOptions, ...options }),
        delete: (url, options = {}) => axios.delete(url, { ...defaultOptions, ...options }),
    };
};

const request = client('MY SECRET TOKEN');

request.get(PAGES_URL);

Dans ce client, vous pouvez également récupérer le jeton à partir du localStorage / cookie, comme vous le souhaitez.

2 votes

Que se passe-t-il si vous voulez que le request.get() ait des en-têtes "application-type". Avec votre approche, les en-têtes de defaultOptions seront écrasés par les en-têtes de request. Ai-je raison ? Merci.

16voto

elQueFaltaba Points 127

De même, nous avons une fonction pour définir ou supprimer le jeton à partir d'appels comme celui-ci :

import axios from 'axios';

export default function setAuthToken(token) {
  axios.defaults.headers.common['Authorization'] = '';
  delete axios.defaults.headers.common['Authorization'];

  if (token) {
    axios.defaults.headers.common['Authorization'] = `${token}`;
  }
}

Nous nettoyons toujours le jeton existant à l'initialisation, puis nous établissons le jeton reçu.

5voto

Paul. B Points 714

Si vous voulez appeler d'autres routes api à l'avenir et garder votre jeton dans le magasin, essayez alors utilisation du middleware redux .

L'intergiciel pourrait écouter l'action d'une api et distribuer les demandes d'api à travers axios en conséquence.

Voici un exemple très simple :

actions/api.js

export const CALL_API = 'CALL_API';

function onSuccess(payload) {
  return {
    type: 'SUCCESS',
    payload
  };
}

function onError(payload) {
  return {
    type: 'ERROR',
    payload,
    error: true
  };
}

export function apiLogin(credentials) {
  return {
    onSuccess,
    onError,
    type: CALL_API,
    params: { ...credentials },
    method: 'post',
    url: 'login'
  };
}

intergiciel/api.js

import axios from 'axios';
import { CALL_API } from '../actions/api';

export default ({ getState, dispatch }) => next => async action => {
  // Ignore anything that's not calling the api
  if (action.type !== CALL_API) {
    return next(action);
  }

  // Grab the token from state
  const { token } = getState().session;

  // Format the request and attach the token.
  const { method, onSuccess, onError, params, url } = action;

  const defaultOptions = {
    headers: {
      Authorization: token ? `Token ${token}` : '',
    }
  };

  const options = {
    ...defaultOptions,
    ...params
  };

  try {
    const response = await axios[method](url, options);
    dispatch(onSuccess(response.data));
  } catch (error) {
    dispatch(onError(error.data));
  }

  return next(action);
};

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X