सभी अक्षीय अनुरोधों के लिए प्राधिकरण शीर्ष लेख संलग्न करें


130

मेरे पास एक प्रतिक्रिया / रिडक्स एप्लिकेशन है जो एक एपीआई सर्वर से टोकन प्राप्त करता है। उपयोगकर्ता द्वारा प्रमाणित किए जाने के बाद, मैं सभी अक्षीय अनुरोध करना चाहता हूं कि एक प्राधिकरण हेडर के रूप में टोकन को मैन्युअल रूप से कार्रवाई में प्रत्येक अनुरोध के बिना संलग्न किया जाए। मैं प्रतिक्रिया / रिड्यूस करने के लिए काफी नया हूं और सर्वश्रेष्ठ दृष्टिकोण पर यकीन नहीं कर रहा हूं और Google पर कोई गुणवत्ता हिट नहीं पा रहा हूं।

यहाँ मेरा 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;
  }
}

मेरा टोकन Redux स्टोर में संग्रहीत है state.session.token

मैं थोड़ा आगे बढ़ने के लिए खो रहा हूँ। मैंने अपनी रूट डाइरेक्टरी में एक फाइल में एक axios इंस्टेंस बनाने की कोशिश की है और नोड_मॉड्यूल्स के बजाय इसे अपडेट / इम्पोर्ट / अपडेट करता हूं, लेकिन जब स्टेट्स बदलता है तो यह हेडर अटैच नहीं होता है। किसी भी प्रतिक्रिया / विचारों की बहुत सराहना की जाती है, धन्यवाद।


सर्वर से टोकन प्राप्त होने के बाद आप प्राधिकरण को कहां संग्रहीत कर रहे हैं? स्थानीय भंडार?
हार्दिक मोद

में redux store session.token
awwester

जवाबों:


202

इसे प्राप्त करने के कई तरीके हैं। यहाँ, मैंने दो सबसे आम दृष्टिकोणों के बारे में बताया है।

1. आप किसी भी अनुरोध को रोकने और प्राधिकरण हेडर जोड़ने के लिए axios इंटरसेप्टर का उपयोग कर सकते हैं ।

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

    return config;
});

2. आप के प्रलेखन से axiosदेख सकते हैं कि एक तंत्र उपलब्ध है जो आपको डिफ़ॉल्ट हेडर सेट करने की अनुमति देता है जिसे आपके द्वारा किए गए प्रत्येक अनुरोध के साथ भेजा जाएगा।

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

तो आपके मामले में:

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

यदि आप चाहें, तो आप एक स्व-निष्पादन योग्य फ़ंक्शन बना सकते हैं जो स्टोर में टोकन मौजूद होने पर खुद ही प्राधिकरण हेडर सेट कर देगा।

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

अब आपको प्रत्येक अनुरोध पर मैन्युअल रूप से टोकन संलग्न करने की आवश्यकता नहीं है। आप उपरोक्त फ़ंक्शन को उस फ़ाइल में रख सकते हैं जो हर बार निष्पादित होने की गारंटी है ( जैसे: फ़ाइल जिसमें रूट शामिल हैं)।

आशा करता हूँ की ये काम करेगा :)


1
पहले से ही redux-persist का उपयोग कर, लेकिन हेडर में टोकन संलग्न करने के लिए मिडलवेयर पर एक नज़र डालेंगे, धन्यवाद!
एवेस्टर

1
@awwस्टर आपको हेडर में टोकन संलग्न करने के लिए मिडलवेयर की आवश्यकता नहीं है। हेडर में टोकन संलग्न axios.defaults.header.common[Auth_Token] = tokenकरना उतना ही सरल है।
हार्दिक मोधा

4
@HardikModha मैं उत्सुक हूं कि फ़ेच एपीआई के साथ कोई ऐसा कैसे कर सकता है।
रॉलैंड

@ रॉलैंड मुझे विश्वास है, आपको इसे प्राप्त करने के लिए भ्रूण एपीआई पर एक आवरण लिखना होगा। उस प्रश्न का विस्तृत उत्तर ओपी द्वारा पूछे गए प्रश्न के दायरे से बाहर है। आप एक और सवाल पूछ सकते हैं :)
हार्दिक मोद

2
हाय @ हार्दिकमोढ़ा। अगर मैं सेट टोकन के लिए डिफ़ॉल्ट हेडर का उपयोग करता हूं जब मैं टोकन को नवीनीकृत करना चाहता हूं, तो यह फिर से हेडर में सेट नहीं किया जा सकता है। क्या यह सही है? इसलिए मुझे इंटरसेप्टर्स का उपयोग करना होगा।
बिग्रेडिवर

50

यदि आप "axios" का उपयोग करते हैं: "^ 0.17.1" संस्करण आप इस तरह कर सकते हैं:

अक्षतंतु का उदाहरण बनाएँ:

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

फिर किसी भी अनुरोध के लिए टोकन लोकलस्टोरेज से चुना जाएगा और अनुरोध हेडर में जोड़ा जाएगा।

मैं इस कोड के साथ ऐप पर एक ही उदाहरण का उपयोग कर रहा हूं:

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

सौभाग्य।


@ Nguy thenPhúc आनंद के साथ, पूरे बिंदु अक्षीयता के "इंटरसेप्टर" का उपयोग करना है
llioor

यह सबसे अच्छा जवाब है ... प्रत्येक अनुरोध के लिए इंटरसेप्टर्स पर टोकन को इनिशियलाइज़ करने के लिए! । साभार
इक्का दुक्का

45

मेरे लिए सबसे अच्छा समाधान एक ग्राहक सेवा बनाना है जिसे आप अपने टोकन से लपेटने के लिए उपयोग कर सकते हैं 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);

इस क्लाइंट में, आप लोकलस्टोरेज / कुकी से टोकन भी प्राप्त कर सकते हैं, जैसा आप चाहते हैं।


1
क्या होगा यदि आप "एप्लिकेशन-टाइप" हेडर के साथ request.get () बनाना चाहते हैं। आपके दृष्टिकोण के साथ डिफॉल्ट से हेडर अनुरोध से हेडर द्वारा हटा दिए जाएंगे। मैं सही हूँ? धन्यवाद।
निप्रो

9

इसी तरह, हमारे पास टोकन को इस तरह से कॉल करने या हटाने का कार्य है:

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

हम प्रारंभ में हमेशा मौजूदा टोकन को साफ करते हैं, फिर प्राप्त एक को स्थापित करते हैं।


5

यदि आप भविष्य में अन्य एपी मार्गों को कॉल करना चाहते हैं और स्टोर में अपना टोकन रखना चाहते हैं, तो redux मिडलवेयर का उपयोग करके देखें

मिडलवेयर एक एपीआई कार्रवाई के लिए सुन सकता है और तदनुसार एक्सियो के माध्यम से एपि अनुरोधों को भेज सकता है।

यहाँ एक बहुत ही बुनियादी उदाहरण है:

कार्यों / 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'
  };
}

मिडलवेयर / 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

कभी-कभी आपको एक ऐसा मामला मिलता है जहां अक्षतंतु के साथ किए गए कुछ अनुरोधों को अंतिम बिंदुओं के लिए इंगित किया जाता है जो प्राधिकरण हेडर स्वीकार नहीं करते हैं। इस प्रकार, अनुमत डोमेन पर केवल प्राधिकरण हेडर सेट करने का वैकल्पिक तरीका नीचे दिए गए उदाहरण में है। किसी भी फ़ाइल में निम्न फ़ंक्शन को रखें जो हर बार निष्पादित हो जाता है रिएक्ट एप्लिकेशन रूट फ़ाइल में चलता है।

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

नए उदाहरण बनाने की कोशिश करें जैसे मैंने नीचे किया है

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

इसे कैसे उपयोग करे

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

कुछ समानों को लागू करने की कोशिश में भाग गया और इन उत्तरों के आधार पर यह वही है जो मैं लेकर आया था। मैं जिन समस्याओं का सामना कर रहा था, वे थीं:

  1. यदि आपके स्टोर में एक टोकन प्राप्त करने के अनुरोध के लिए axios का उपयोग कर रहे हैं, तो आपको शीर्षलेख जोड़ने से पहले पथ का पता लगाने की आवश्यकता है। यदि आप नहीं करते हैं, तो यह हेडर को उस कॉल में जोड़ने के साथ-साथ एक परिपत्र पथ समस्या में लाने का प्रयास करेगा। अन्य कॉल का पता लगाने के लिए रेगेक्स को जोड़ने का विलोम भी काम करेगा
  2. यदि स्टोर एक वादा वापस कर रहा है, तो आपको ओर्डहैंडलर फ़ंक्शन में वादे को हल करने के लिए स्टोर पर कॉल वापस करने की आवश्यकता है। Async / Await कार्यक्षमता इस आसान / अधिक स्पष्ट कर देगा
  3. यदि टोकन टोकन के लिए कॉल विफल हो जाता है या टोकन प्राप्त करने के लिए कॉल है, तो आप अभी भी कॉन्फ़िगरेशन के साथ एक वादा हल करना चाहते हैं

0

बिंदु प्रत्येक अनुरोध के लिए इंटरसेप्टर पर टोकन सेट करना है

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;
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.