Tüm axios istekleri için Yetkilendirme başlığı ekleyin


131

Bir api sunucusundan bir belirteç alan bir react / redux uygulamam var. Kullanıcı kimlik doğrulamasını yaptıktan sonra, tüm axios isteklerinin, eylemdeki her isteğe manuel olarak eklemek zorunda kalmadan bu belirteci bir Yetkilendirme başlığı olarak almasını istiyorum. Tepki verme / yeniden düzenleme konusunda oldukça yeniyim ve en iyi yaklaşımdan emin değilim ve google'da herhangi bir kaliteli hit bulamıyorum.

İşte redux kurulumum:

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

Simgem, altındaki redux mağazasında saklanıyor state.session.token.

Nasıl ilerleyeceğim konusunda biraz kayboldum. Kök dizinimdeki bir dosyada bir axios örneği yapmayı ve bunu node_modules yerine güncellemeyi / içe aktarmayı denedim, ancak durum değiştiğinde başlık eklemiyor. Herhangi bir geri bildirim / fikir çok takdir edilmektedir, teşekkürler.


Jeton sunucudan alındıktan sonra yetkilendirme jetonunu nerede saklıyorsunuz? yerel depolama?
Hardik Modha

redux mağaza session.token
awwester

Yanıtlar:


205

Bunu başarmanın birden çok yolu var. Burada en yaygın iki yaklaşımı açıkladım.

1. Axios engelleyicileri herhangi bir isteği durdurmak ve yetkilendirme başlıkları eklemek için kullanabilirsiniz .

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

    return config;
});

2. Belgelerden , axiosyaptığınız her istekte gönderilecek olan varsayılan başlığı ayarlamanıza izin veren bir mekanizma olduğunu görebilirsiniz.

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

Yani senin durumunda:

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

İsterseniz, belirteç mağazada mevcut olduğunda yetkilendirme başlığını kendisi ayarlayacak kendi kendine çalıştırılabilir bir işlev oluşturabilirsiniz.

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

Artık her isteğe manuel olarak jeton eklemenize gerek yok. Yukarıdaki işlevi, her seferinde çalıştırılması garantilenen dosyaya yerleştirebilirsiniz ( örn: yolları içeren dosya).

Umarım yardımcı olur :)


1
zaten redux-persist kullanıyor ancak token'ı başlığa eklemek için ara yazılımlara bir göz atacağız, teşekkürler!
awwester

1
@awwester Belirteci başlığa eklemek için ara katman yazılımına ihtiyacınız yoktur. Başlığa jeton eklemek bu axios.defaults.header.common[Auth_Token] = tokenkadar basit.
Hardik Modha

4
@HardikModha Bunu Fetch API ile nasıl yapabileceğinizi merak ediyorum.
Rowland

@Rowland İnanıyorum ki, aynı şeyi başarmak için getirme API'si üzerine bir sarmalayıcı yazmanız gerekecek. Bu sorunun ayrıntılı cevabı, OP tarafından sorulan sorunun kapsamı dışındadır. Başka bir soru sorabilirsiniz :)
Hardik Modha

2
Merhaba @HardikModha. Belirteci yenilemek istediğimde set belirteci için varsayılan üstbilgileri kullanırsam, başlığa yeniden ayarlanamaz. doğru mu? Yani önleyicileri kullanmalıyım.
beginerdeveloper

51

"Axios": "^ 0.17.1" sürümünü kullanıyorsanız, şu şekilde yapabilirsiniz:

Aksiyolar örneği oluşturun:

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

Daha sonra herhangi bir istek için belirteç localStorage'dan seçilecek ve istek başlıklarına eklenecektir.

Bu kodla uygulamanın her yerinde aynı örneği kullanıyorum:

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

İyi şanslar.


@ NguyenễnPhúc Zevkle, bütün mesele axios'un "önleyicilerini" kullanmak
llioor

En iyi cevap budur ... her istek için önleyicilerde belirteci başlatmak için! . Teşekkürler
james ace

45

Benim için en iyi çözüm, belirtecinizle somutlaştıracağınız ve sarmak için kullanacağınız bir istemci hizmeti oluşturmaktır 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);

Bu istemcide, belirteci localStorage / çerezden de istediğiniz gibi alabilirsiniz.


1
"Application-type" üstbilgileri ile request.get () yapmak isterseniz ne olur? Yaklaşımınızla, defaultOptions'tan gelen başlıkların üzerine istek başlıkları eklenecektir. Haklıyım? Teşekkür ederim.
nipuro

9

Benzer şekilde, belirteci aşağıdaki gibi çağrılardan ayarlamak veya silmek için bir işlevimiz var:

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

Mevcut jetonu her zaman başlangıçta temizleriz, ardından alınan jetonu oluştururuz.


5

Gelecekte diğer API yollarını aramak ve jetonunuzu mağazada tutmak istiyorsanız, redux ara yazılımını kullanmayı deneyin .

Ara yazılım bir api eylemini dinleyebilir ve api isteklerini aksiyolar aracılığıyla gönderebilir.

İşte çok basit bir örnek:

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

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

3

Bazen aksiyolarla yapılan bazı taleplerin yetkilendirme başlıklarını kabul etmeyen uç noktalara yönlendirildiği bir durumla karşılaşırsınız. Bu nedenle, yetkilendirme başlığını yalnızca izin verilen alanda ayarlamanın alternatif yolu aşağıdaki örnekte olduğu gibidir. Aşağıdaki işlevi, React uygulaması her çalıştığında, örneğin route dosyası gibi, çalıştırılan herhangi bir dosyaya yerleştirin.

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

Aşağıda yaptığım gibi yeni bir örnek oluşturmaya çalışın

var common_axios = axios.create({
    baseURL: 'https://sample.com'
});

// Set default headers to common_axios ( as Instance )
common_axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
// Check your Header
console.log(common_axios.defaults.headers);

Bu nasıl kullanılır

common_axios.get(url).......
common_axios.post(url).......

0
export const authHandler = (config) => {
  const authRegex = /^\/apiregex/;

  if (!authRegex.test(config.url)) {
    return store.fetchToken().then((token) => {
      Object.assign(config.headers.common, { Authorization: `Bearer ${token}` });
      return Promise.resolve(config);
    });
  }
  return Promise.resolve(config);
};

axios.interceptors.request.use(authHandler);

Benzer bir şeyi uygulamaya çalışırken bazı sorunlarla karşılaştım ve bu cevaplara dayanarak bulduğum şey buydu. Yaşadığım sorunlar şunlardı:

  1. Mağazanızda jeton alma isteği için aksiyolar kullanıyorsanız, başlığı eklemeden önce yolu tespit etmeniz gerekir. Yapmazsanız, başlığı o çağrıya eklemeye ve döngüsel bir yol sorununa girmeye çalışacaktır. Diğer çağrıları algılamak için normal ifade eklemenin tersi de işe yarar
  2. Mağaza bir sözü iade ediyorsa, authHandler işlevindeki sözü çözmek için çağrıyı mağazaya geri göndermeniz gerekir. Async / Await işlevi bunu daha kolay / daha belirgin hale getirir
  3. Yetkilendirme belirteci çağrısı başarısız olursa veya belirteci alma çağrısıysa, yine de yapılandırma ile bir sözü çözmek istersiniz.

0

Önemli olan, jetonu her istek için engelleyiciler üzerinde ayarlamaktır.

import axios from "axios";
    
const httpClient = axios.create({
    baseURL: "http://youradress",
    // baseURL: process.env.APP_API_BASE_URL,
});

httpClient.interceptors.request.use(function (config) {
    const token = localStorage.getItem('token');
    config.headers.Authorization =  token ? `Bearer ${token}` : '';
    return config;
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.