programing

401(Authentication Error)을 액시스로 처리하여 어떻게 대응합니까?

muds 2023. 4. 1. 10:06
반응형

401(Authentication Error)을 액시스로 처리하여 어떻게 대응합니까?

axios ajax 요청에 대한 래퍼가 포함된 request.js 파일이 하나 있습니다.여러 리액트 컴포넌트에서 요청 함수를 호출하고 있으며 요청 중 하나가 실패하면 토큰을 새로 고치고 실패한 모든 요청을 다시 시도합니다.인터셉터를 사용할 수는 있지만 어떻게 구현해야 할지 모르겠어요.제발 도와주세요.

request.request.discloss를 실행합니다.

 var client = axios.create({
   baseURL: 'http://192.168.1.3:3000',
     headers: {
     appID: 8,
     version: "1.1.0",
     empID: localStorage.getItem('empID'),
     token: localStorage.getItem('accessToken')
    }
 });

 const request = function(options) {
     const onSuccess = function(response) {
         console.debug('Request Successful!', response);
         return response.data;
     } 
     const onError = function(error) {
         console.error('Request Failed:', error.config);
         if (error.response) {
             console.error('Status:',  error.response.status);
             console.error('Data:',    error.response.data);
             console.error('Headers:', error.response.headers);
         } else {
             console.error('Error Message:', error.message);
         }

         return Promise.reject(error.response || error.message);
     }

     return client(options)
         .then(onSuccess)
         .catch(onError);
         options
 }

 export default request;

401 오류를 처리하기 위해 가로채기를 사용하는 경우 코드 스니펫이 있습니다.

axios.interceptors.response.use(response => {
   return response;
}, error => {
  if (error.response.status === 401) {
   //place your reentry code
  }
  return error;
});

이 방법은 다음과 같습니다.

// Add a 401 response interceptor
window.axios.interceptors.response.use(function (response) {
    return response;
}, function (error) {
    if (401 === error.response.status) {
        // handle error: inform user, go to login, etc
    } else {
        return Promise.reject(error);
    }
});

출처: https://gist.github.com/yajra/5f5551649b20c8f668aec48549ef5c1f

난 또 다른 문제가 있었어:

응답이 없는 "네트워크 오류"

tl;dr - CORS와 설정 방법에 문제가 있어 악시스는 브라우저로부터 정보를 얻을 수 없었습니다.서버측에서 분류해야 합니다.

묘사

유사한 문제가 있는 경우 브라우저 콘솔에 표시됩니다.브라우저는 Ajax를 통해 다른 URL에 액세스할 수 없도록 합니다.

제 경우(node.js - express)는 필터 순서입니다.이 특정 요구에 대한 핸들러 뒤에 CORS 필터(dev 환경)가 추가되어 서버가 적절한 CORS 헤더를 송신하고 있지 않았기 때문에 브라우저는 요구를 실행할 수조차 없었습니다(서버에 대한 호출은 전혀 없었습니다).에러 오브젝트가 반환되지 않았습니다).

다음 코드로 작업했습니다.

import axios from 'axios';
import config from '../../configuration.json';
import qs from 'qs';

const baseURL = config['baseUrl_local'];
let authTokenRequest;

/**
  * @description axios instance for ajax requests
*/ 

var client = axios.create({
baseURL: baseURL,
headers: {
    appID: 8,
    version: "1.1.0",
    empID: localStorage.getItem('empID'),
    token: localStorage.getItem('accessToken')
}
});

/**
 * @description this method calls a requestNewToken method to issue a 
 new token to the client
*/ 

 function getAuthToken() {
   if (!authTokenRequest) {
   authTokenRequest = requestNewToken();
   authTokenRequest.then(resetAuthTokenRequest, resetAuthTokenRequest);
 }
 return authTokenRequest;
 }

/**
  * @description this method requests the server to issue a new token, 
  the server response is updated in local storage accessToken
*/ 

function requestNewToken() {
  var newToken = request({
  method: "post",
  url: '/sign-in',
  data:  qs.stringify({
         "userName":localStorage.getItem('userName'),
         "password":localStorage.getItem('password')
         })  
  }).then((res)=>{
  if(res.status == "success"){
    localStorage.setItem('accessToken',res.data.accessToken);
    //if featureArray is present in response object, update the 
    featureArray in local storage
    if(res.data.features){
      localStorage.setItem(
      'featureArray',
     JSON.stringify(res.data.features));
    }
    client = axios.create({
     baseURL: baseURL,
     headers: {
          appID: 8,
          version: "1.1.0",
          empID: localStorage.getItem('empID'),
          token: localStorage.getItem('accessToken')
      }
   });
 } else {
  window.location = "/logout";
 }
});
 return newToken;
}

function resetAuthTokenRequest() {
  authTokenRequest = null;
 }

/**
  * @description if any of the API gets 401 status code, this method 
   calls getAuthToken method to renew accessToken
  * updates the error configuration and retries all failed requests 
  again
*/ 

client.interceptors.response.use(undefined, err => {
  const error = err.response;
  // if error is 401 
  if (error.status===401 && error.config && 
  !error.config.__isRetryRequest) {
  // request for a new token
  return getAuthToken().then(response => {
   // update the error config with new token
   error.config.__isRetryRequest = true;
   error.config.headers.token= localStorage.getItem("accessToken");
   return client(error.config);
  });
 } 
});

/**
 * @description wrapper for making ajax requests
 * @param {object} object with method,url,data etc.
*/ 

const request = function(options) {
  const onSuccess = function(response) {
    return response.data;
  }
 const onError = function(error) {
  //console.error('Request Failed:', error.config);
   if (error.response) {
  //console.error('Status:',  error.response.status);
  //console.error('Data:',    error.response.data);
  //console.error('Headers:', error.response.headers);
  } else {
  console.error('Error Message:', error.message);
  }
 return Promise.reject(error.response || error.message);
 }

return client(options)
        .then(onSuccess)
        .catch(onError);
        options
}

export default request;

【편집】2019년입니다만, 또 다른 실장입니다.위의 솔루션은 훌륭하지만 여러 번 실패한 요청에서는 제대로 작동하지 않습니다.그 결과 콜은업데이트된 토큰이 포함된 토큰도 있습니다.

 import axios from "axios";

 /* @internal */
 import config from "../config";
 import TokenService from "./token_service";

class Request {
    constructor() {
        this.baseURL = config.baseUrl;
        this.isRefreshing = false;
        this.failedRequests = [];
        this.tokenService = new TokenService();
        this.client = axios.create({
            baseURL: config.apiServerBaseUrl,
            headers: {
               clientSecret: this.clientSecret,
            },
        });
        this.beforeRequest = this.beforeRequest.bind(this);
        this.onRequestFailure = this.onRequestFailure.bind(this);
        this.processQueue = this.processQueue.bind(this);
        this.client.interceptors.request.use(this.beforeRequest);
        this.client.interceptors.response.use(this.onRequestSuccess, 
this.onRequestFailure);
}

beforeRequest(request) {
    const token = TokenService.getAccessToken();
    request.headers.Authorization = `Token ${token}`;
    return request;
}

static onRequestSuccess(response) {
    return response.data;
}

async onRequestFailure(err) {
    const { response } = err;
    if (response.status === 401 && err && err.config && !err.config.__isRetryRequest) {
        if (this.isRefreshing) {
            try {
                const token = await new Promise((resolve, reject) => {
                    this.failedRequests.push({ resolve, reject });
                });
                err.config.headers.Authorization = `Bearer ${token}`;
                return this.client(err.config);
            }
            catch (e) {
                return e;
            }
        }
        this.isRefreshing = true;
        err.config.__isRetryRequest = true;
        return new Promise((resolve, reject) => {
            this.tokenService.refreshAccessToken().then((token) => {
                this.tokenService.setAccessToken(token);
                err.config.headers.Authorization = `Bearer ${token}`;
                this.isRefreshing = false;
                this.processQueue(null, token);
                resolve(this.client(err.config));
            }).catch((e) => {
                this.processQueue(e, null);
                reject(err.response);
            });
        });
    }
    throw response;
}

processQueue(error, token = null) {
    this.failedRequests.forEach((prom) => {
        if (error) {
            prom.reject(error);
        } else {
            prom.resolve(token);
        }
       });
        this.failedRequests = [];
    }

}

const request = new Request();

export default request.client;

이 방법으로 공리 401을 잡을 수 있습니다.

 axios.post('/add')
 .then(function (response) {...})
 .catch(function (error) {
     console.log(error.response.status) // 401
     console.log(error.response.data.error) //Please Authenticate or whatever returned from server
   if(error.response.status==401){
     //redirect to login
   }
 })

몇 가지 다른 질문을 드렸는데, 여기 제 코드가 있습니다.

import axios from 'axios';

const instance = axios.create({
    baseURL: window.location.hostname === 'localhost' ? 'http://localhost:5001/api/v1' : 'https://api.mysite.com/api/v1'
});
instance.defaults.headers.common['Content-Type'] = 'multipart/form-data';

//validate response
instance.interceptors.response.use((response) => {
    return response;
}, (error) => {
        if (error.response.status === 401) {

            return window.location.href = '/login'
        }
    return Promise.reject(error);
});

// Set the AUTH token for any request
instance.interceptors.request.use(
    (config) => {
        const token = localStorage.getItem('token');
        config.headers.Authorization =  token ? `Bearer ${token}` : '';
        return config;
    }
)

export default instance;

모듈에서 Axios를 사용할 때 명확한 답을 찾을 수 없었습니다.인터셉터를 사용하고 있는 악리의 인스턴스에 추가해야 합니다.

api.module

import axios from 'axios'
import store from '../state'

//Defaults will be combined with the instance
axios.defaults.baseURL = '/some/page.aspx';

//Create Axios Instance
const axiosInstance = axios.create({
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json; charset=UTF-8'
    }
});

//Add interceptors to instance
axiosInstance.interceptors.response.use(
    response => response,
    error => {
        if (!error.response) {
            store.commit('setServiceAvailable', false);
        }
        else if (error.response.status === 401) {
            store.commit('setUserAuthorised', false);
        }
        return error;
    });

export default axiosInstance;

그런 다음 정상적으로 사용

component.displaces(컴포넌트).

import api from '../api'
...
async getServersJson() {
    try {
        var response = await api.post('GetReportAsServers', {name: 'get-servers', args: null});
        this.serversJson = this.prettifyJson(response.data.d);
    }
    catch (error) {
        console.error(`Exception getting servers. ${error}`);
    }
},

언급URL : https://stackoverflow.com/questions/47216452/how-to-handle-401-authentication-error-in-axios-and-react

반응형