programing

모든 Axios 요청에 대한 Authorization 헤더 첨부

codeshow 2023. 4. 2. 11:41
반응형

모든 Axios 요청에 대한 Authorization 헤더 첨부

api 서버에서 토큰을 가져오는 react/redux 응용 프로그램이 있습니다.사용자가 인증한 후 액션의 모든 요청에 수동으로 연결하지 않고 모든 Axios 요청에 해당 토큰을 Authorization 헤더로 지정하려고 합니다.저는 리액션/리덕스를 처음 접하는 사람이라 최선의 접근법에 대해 확신이 없고 구글에서 질 높은 히트를 찾을 수 없습니다.

레독스 설정은 다음과 같습니다.

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

내 토큰은 아래 레독스 스토어에 저장됩니다.state.session.token.

어떻게 해야 할지 모르겠어요.루트 디렉토리에 있는 파일에 axios 인스턴스를 만들어 node_modules 대신 업데이트/import를 시도했지만 상태가 바뀌어도 헤더가 연결되지 않습니다.피드백/아이디어에 감사드립니다.

이를 실현하는 방법은 여러 가지가 있습니다.여기에서는 가장 일반적인 두 가지 접근법에 대해 설명했습니다.

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 인스턴스 만들기:

// 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/cookie에서 토큰을 검색할 수도 있습니다.

마찬가지로 다음과 같은 콜에서 토큰을 설정 또는 삭제하는 기능이 있습니다.

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

초기화 시 항상 기존 토큰을 클리어하고 수신한 토큰을 확립합니다.

요점은 각 요구에 대해 인터셉터에 토큰을 설정하는 것입니다.

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

향후 다른 API 루트를 호출하여 토큰을 스토어에 보관하고 싶다면 redux 미들웨어를 사용해 보십시오.

미들웨어는 api 액션을 리슨하고 그에 따라 api 요구를 acios를 통해 디스패치할 수 있습니다.

다음으로 매우 기본적인 예를 제시하겠습니다.

actions/api.syslog

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

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

경우에 따라서는 악리로 이루어진 요청 중 일부가 인가 헤더를 받지 않는 엔드포인트를 가리킬 수 있습니다.따라서 허가 도메인에만 인가 헤더를 설정하는 대체 방법은 다음과 같습니다.routes file과 같이 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).......
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. 저장소에서 토큰을 가져오는 요청에 액시오스를 사용하는 경우 헤더를 추가하기 전에 경로를 감지해야 합니다.그렇지 않으면 해당 콜에도 헤더가 추가되어 순환 경로 문제가 발생합니다.다른 콜을 검출하기 위해 regex를 추가하는 반대의 경우도 기능합니다.
  2. 스토어가 약속을 반환하는 경우 authHandler 함수의 약속을 해결하려면 콜을 스토어에 반환해야 합니다.비동기/Awit 기능을 사용하면 보다 쉽게/명확해질 수 있습니다.
  3. 인증 토큰 콜이 실패하거나 토큰을 취득하기 위한 콜인 경우에도 Configuration과의 약속을 해결해야 합니다.

언급URL : https://stackoverflow.com/questions/43051291/attach-authorization-header-for-all-axios-requests

반응형