모든 axios 요청에 대한 인증 헤더 첨부

API 서버에서 토큰을 가져 오는 react / redux 애플리케이션이 있습니다. 사용자가 인증 한 후 모든 axios 요청이 작업의 모든 요청에 ​​수동으로 첨부 할 필요없이 해당 토큰을 Authorization 헤더로 갖도록 만들고 싶습니다. 나는 반응 / redux를 처음 접했으며 최선의 접근 방식을 확신하지 못하며 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 인스턴스 를 만들고 node_modules 대신 업데이트 / 가져 오기를 시도했지만 상태가 변경 될 때 헤더를 첨부하지 않습니다. 모든 피드백 / 아이디어는 대단히 감사합니다.



답변

이를 달성하는 방법에는 여러 가지가 있습니다. 여기서는 가장 일반적인 두 가지 접근 방식을 설명했습니다.

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

이제 더 이상 모든 요청에 ​​수동으로 토큰을 첨부 할 필요가 없습니다. 위의 함수는 매번 실행되도록 보장되는 파일에 넣을 수 있습니다 ( 예 : 경로가 포함 된 파일).

도움이되기를 바랍니다 🙂


답변

“axios”: “^ 0.17.1″버전을 사용하는 경우 다음과 같이 할 수 있습니다.

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

그런 다음 모든 요청에 ​​대해 토큰이 localStorage에서 선택되고 요청 헤더에 추가됩니다.

이 코드를 사용하여 앱 전체에서 동일한 인스턴스를 사용하고 있습니다.

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

행운을 빕니다.


답변

나에게 가장 좋은 해결책은 토큰으로 인스턴스화하고이를 래핑하는 데 사용할 클라이언트 서비스를 만드는 것 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);

이 클라이언트에서는 원하는대로 localStorage / 쿠키에서 토큰을 검색 할 수도 있습니다.


답변

마찬가지로 다음과 같은 호출에서 토큰을 설정하거나 삭제하는 함수가 있습니다.

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

초기화시 항상 기존 토큰을 정리 한 다음받은 토큰을 설정합니다.


답변

나중에 다른 API 경로를 호출하고 토큰을 저장소에 유지하려면 redux 미들웨어 를 사용해보십시오 .

미들웨어는 api 작업을 수신하고 그에 따라 axios를 통해 api 요청을 전달할 수 있습니다.

다음은 매우 기본적인 예입니다.

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


답변

때때로 axios로 이루어진 일부 요청이 인증 헤더를 허용하지 않는 엔드 포인트를 가리키는 경우가 있습니다. 따라서 허용 된 도메인에서만 인증 헤더를 설정하는 다른 방법은 아래 예와 같습니다. Route 파일과 같이 React 애플리케이션이 실행될 때마다 실행되는 파일에 다음 함수를 배치합니다.

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

}


답변

아래 에서처럼 새 인스턴스를 만드십시오.

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