Как мы можем поддерживать пользователя в системе, когда срок действия токена доступа истекает, и нам нужно снова войти в систему, чтобы продолжить работу как обычный пользователь

Я использую модуль Nuxt-axios с прокси.

Для обработки ошибок у меня есть общий код в

Плагины / axios.js

export default function({ $axios, __isRetryRequest, store, app, redirect , payload , next}) {
  $axios.onRequest(config => {
  if (app.$cookies.get('at') && app.$cookies.get('rt') && config.url != '/post_login/') {
      config.headers.common['Authorization'] = `Bearer ${app.$cookies.get('at')}`;
    }
  });

  $axios.onResponseError(err => {
    const code = parseInt(err.response && err.response.status)

    let originalRequest = err.config;

    if (code === 401) {
      originalRequest.__isRetryRequest = true;

      store
        .dispatch('LOGIN', { grant_type: 'refresh_token', refresh_token: app.$cookies.get('rt')})
        .then(res => {
          originalRequest.headers['Authorization'] = 'Bearer ' + app.$cookies.get('at');
          return app.$axios(originalRequest);
        })
        .catch(error => {
          console.log(error);
        });
    }

    // code for 422 error
    if (code == 422) {
      throw err.response;
    }

  });
}

На странице индекса моей папки

Pages / index.vue

<template>
  <section>Component data</section>
</template>

<script type="text/javascript">
export default {
  async asyncData({ route, store }) {
    await store.dispatch('GET_BANNERS');
  }
}
</script>

Все вызовы API находятся в файле stroes / actions.js.

Теперь вопрос в том, когда я обновляю страницу index.vue, первый запрос API попадет и в случае успеха получит ответ. Но теперь, если при первом запросе ('GET_BANNERS') от asyncData он получает несанкционированную ошибку 401, я получаю ошибку ниже

Error: Request failed with status code 401

Ошибка [ERR_HTTP_HEADERS_SENT]: невозможно установить заголовки после их отправки клиенту.

как я могу это решить?

еще несколько вопросов:

1) Когда я пишу общий код ошибки в axios, исходный запрос, по которому я получил 401, как я могу снова настроить данные для сохранения (что мы обычно делаем из файла действий)?

2) может ли кто-нибудь помочь с передовой практикой прикрепить заголовки авторизации и дескриптор ошибки для 400 401 422 и т. Д.


person Hardik Shah    schedule 08.07.2018    source источник
comment
Решена неавторизованная проблема 401   -  person Hardik Shah    schedule 22.09.2018


Ответы (2)


$axios.onResponseError(err => {
  const code = parseInt(err.response && err.response.status);

  let originalRequest = err.config;
  if (code == 401) {
    originalRequest.__isRetryRequest = true;

    let token = app.$cookies.get('rt');

    return new Promise((resolve, reject) => {
      let req = $axios
        .post(`/login`, { grant_type: 'refresh_token', refresh_token: token })
        .then(response => {

          if (response.status == 200) {

              app.$cookies.set('access', response.data.access_token);
              app.$cookies.set('refresh', response.data.refresh_token);
              originalRequest.headers['Authorization'] = `Bearer ${
                response.data.access_token
              }`;
          }
          resolve(response);
        }).catch(e => {
          reject("some message");
        })

      })
      .then(res => {
        return $axios(originalRequest);
      }).catch(e => {
        app.router.push('/login');
      });
  }
});

@ canet-robern надеюсь, что это решит вашу проблему !!

person Hardik Shah    schedule 20.12.2018
comment
Этот ответ сработал для меня. Спасибо - person ohjeeez; 18.03.2021

Ошибка ERR_HTTP_HEADERS_SENT означает, что у вас есть ошибка в коде на стороне сервера - следовательно, ошибка из-за этой ошибки появляется перед заголовками HTTP.

Чтобы обработать ошибки 4xx и повторить запрос Axios, выполните следующий пример:

Vue.prototype.$axios = axios.create(
  {
    headers:
      {
        'Content-Type': 'application/json',
      },
    baseURL: process.env.API_URL
  }
);

Vue.prototype.$axios.interceptors.request.use(
  config =>
  {
    events.$emit('show_spin');
    let token = getTokenID();
    if(token && token.length) config.headers['Authorization'] = token;
    return config;
  },
  error =>
  {
    events.$emit('hide_spin');
    if (error.status === 401) VueRouter.push('/login');
    else throw error;
  }
);
Vue.prototype.$axios.interceptors.response.use(
  response =>
  {
    events.$emit('hide_spin');
    return response;
  },
  error =>
  {
    events.$emit('hide_spin');
    return new Promise(function(resolve,reject)
    {
      if (error.config && error.response && error.response.status === 401 && !error.config.__isRetry)
      {
        myVue.refreshToken(function()
        {
          error.config.__isRetry = true;
          error.config.headers['Authorization'] = getTokenID();
          myVue.$axios(error.config).then(resolve,reject);
        },function(flag) // true = invalid session, false = something else
        {
          if(process.env.NODE_ENV === 'development') console.log('Could not refresh token');
          if(getUserID()) myVue.showFailed('Could not refresh the Authorization Token');
          reject(flag);
        });
      }
      else throw error;
    });
  }
); 
person IVO GELOV    schedule 30.07.2018
comment
Как видите, у меня уже есть 4XX код обработки общих ошибок в Plugins / axios.js. Но теперь мой первый вопрос остается без ответа: когда я пишу общий код ошибки в axios, исходный запрос, по которому я получил 401, как я могу настроить данные для повторного сохранения обработки ошибок, когда 401 упоминается в plugins / axios.js, если ты можешь помочь!!!! - person Hardik Shah; 08.08.2018
comment
Если вы выполните something в действии перед вызовом Axios - тогда, когда вы повторите запрос Axios, вы должны сделать то же thing внутри обработчика повтора. Пожалуйста, опубликуйте сетевой журнал для ответа 401, чтобы мы могли видеть, что приходит по сети с сервера. - person IVO GELOV; 08.08.2018