wake-up-neo.com

Fügen Sie den Autorisierungsheader für alle Axios-Anforderungen hinzu

Ich habe eine Reakt/Redux-Anwendung, die ein Token von einem API-Server abruft. Nachdem der Benutzer sich authentifiziert hat, möchte ich, dass alle Axios-Anforderungen dieses Token als Berechtigungsheader haben, ohne es manuell an jede Anforderung in der Aktion anhängen zu müssen. Ich bin ziemlich neu zu reagieren/redux und bin mir nicht sicher über die beste Vorgehensweise und finde bei Google keine Qualitätstreffer.

Hier ist mein Redux-Setup:

// 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;
  }
}

Mein Token wird im redux store unter state.session.token gespeichert.

Ich bin ein bisschen verloren, wie ich vorgehen soll. Ich habe versucht, eine axios-Instanz in einer Datei in meinem Stammverzeichnis zu erstellen und diese anstelle von node_modules zu aktualisieren/importieren, aber der Header wird nicht angehängt, wenn sich der Status ändert. Jedes Feedback/Ideen sind dankbar.

29
awwester

In der documentation von axios können Sie sehen, dass es einen Mechanismus gibt, mit dem Sie einen Standardheader festlegen können, der mit jeder Anfrage gesendet wird.

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

Also in deinem Fall:

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

Wenn Sie möchten, können Sie eine selbst ausführbare Funktion erstellen, die den Berechtigungsheader selbst setzt, wenn das Token im Geschäft vorhanden ist.

(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'];
         */
     }
})();

Jetzt müssen Sie das Token nicht mehr manuell an jede Anforderung anhängen. Sie können die obige Funktion in die Datei einfügen, die garantiert jedes Mal ausgeführt wird (z. B. Datei, die die Routen enthält).

Ich hoffe es hilft :)

36
Hardik Modha

Die beste Lösung für mich ist, einen Client-Service zu erstellen, den Sie mit Ihrem Token instanziieren und ihn zum Umschließen von axios verwenden.

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

In diesem Client können Sie das Token je nach Wunsch auch von localStorage/cookie abrufen.

28
Kmaschta

Wenn Sie "axios": "^ 0.17.1" verwenden, können Sie dies wie folgt tun:

Instanz von Axios erstellen:

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

Dann wird für jede Anforderung das Token aus localStorage ausgewählt und den Anforderungsheadern hinzugefügt.

Ich verwende in der gesamten App dieselbe Instanz mit diesem 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();

Viel Glück.

22
llioor

Ebenso haben wir eine Funktion, um das Token wie folgt festzulegen oder zu löschen: 

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}`;
  }
}

Wir reinigen das vorhandene Token bei der Initialisierung immer und stellen dann das empfangene fest.

3
elQueFaltaba

Wenn Sie in Zukunft andere API-Routen aufrufen und Ihr Token im Geschäft behalten möchten, versuchen Sie mit redux Middleware .

Die Middleware könnte auf die Aktion eines APIs warten und die API-Anforderungen entsprechend durch axios versenden.

Hier ist ein sehr einfaches Beispiel:

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'
  };
}

middleware/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);
};
2
Paul. B

Manchmal kommt es zu einem Fall, in dem einige der Anforderungen, die mit Axios gemacht werden, auf Endpunkte verweisen, die keine Berechtigungsheader akzeptieren. Eine alternative Möglichkeit, den Autorisierungsheader nur für die zulässige Domäne festzulegen, ist wie im folgenden Beispiel. Platzieren Sie die folgende Funktion in einer Datei, die jedes Mal ausgeführt wird, wenn die React-Anwendung ausgeführt wird, beispielsweise in der Routes-Datei.

export default () => {
    axios.interceptors.request.use(function (requestConfig) {
        if (requestConfig.url.indexOf(<ALLOWED_DOMAIN>) > -1) {
            const token = localStorage.token;
            requestConfig.headers['Authorization'] = `Bearer ${token}`;
        }

        return requestConfig;
    }, function (error) {
        return Promise.reject(error);
    });

}
0