Обработка аксиальных перехватчиков ответа с использованием фляг-коров для обновления токена jwt - PullRequest
0 голосов
/ 09 ноября 2019

Я строю API, используя колбу-restful с токенами jwt для авторизации с помощью vue-интерфейса, используя axios для запросов. Запросы работают правильно, а теги jwt_required и jwt_refresh_token работают должным образом. Я могу войти, я могу получить данные и т.д. без проблем. Проблема, с которой я столкнулся, заключается в том, что я хочу, чтобы пользователь обновил свой токен, если попытался сделать запрос, и произошла неавторизованная ошибка состояния 401, поскольку срок действия маркера истек. Ошибка возвращается как строка, а не как фактическая ошибка, поэтому я не могу проверить «error.status» или получить «error.config», чтобы повторно отправить неудавшийся запрос после обновления токена и обновления заголовков. Я не думаю, что это проблема аксиоса, я думаю, что это проблема cors. Я абсолютно не знаю, что для этого сделать, и я ударил стену после нескольких часов поиска ответов. Я пытался реализовать некоторые решения для подобных проблем, но они не помогли, поэтому я подумал, что должен спросить, как конкретно решить мою проблему, и, надеюсь, ответы могут помочь кому-то еще в будущем.

Я планировал использовать перехватчики axios. Установите токен в перехватчике запроса и используйте перехватчик ответа, чтобы обновить токен в ответе статуса 401 и повторно отправить ранее неудавшийся запрос.

Это моя настройка CORS в колбе

cors = CORS(app, resources={r"/*": {"origins": "*"}}, support_credentials=True, headers=['Content-Type', 'Authorization', 'Access-Control-Allow-Credentials', 'Access-Control-Allow-Origin'],
            expose_headers='Authorization')

Это мой путь обновления токена

class TokenRefresh(Resource):    
    @jwt_refresh_token_required
    def post(self):
        username = get_jwt_identity()
        current_user = User.find_by_username(username)
        if current_user:
            access_token = create_access_token(identity=username)
            refresh_token = create_refresh_token(identity=username)
            return {                
                'access_token': access_token,
                'refresh_token': refresh_token
            }
        else:
            return 'Not a User'

Это моя установка Axios

const API_URL = process.env.VUE_APP_BASE_URL

axios.defaults.headers.post['Content-Type'] = 'application/json;charset=utf-8';
axios.defaults.headers.post['Access-Control-Allow-Origin'] = '*';
axios.defaults.baseURL = API_URL

axios.interceptors.request.use(config => {
    let token = localStorage.getItem('access_token')
    if (config.url.includes('token/refresh')){
        token = localStorage.getItem('refresh_token')
    }  
    config.headers.Authorization = `Bearer ${token}`
    return config;
    }, 
    error => {
        return Promise.reject(error)
    })

axios.interceptors.response.use(response => response, error => {
    console.log(error)
    console.log(error.status)
})

В ответе я хочу обновить токен и повторно отправить старый запрос, но ошибка возвращается в виде строки, а error.status возвращается как неопределенный. Я хотел бы, если возможно, обновить токен с помощью действия vuex, чтобы мои токены могли одновременно храниться в состоянии. Модель того, что я имел в виду, но не работает, выглядит примерно так

axios.interceptors.response.use(response => response, error => {
    if (error.status === 401){
        this.dispatch('refreshUser')
        let newtoken = localStorage.getItem('access_token')
        error.headers.Authorization = `Bearer ${newtoken}`
        return axios.request(error.config)
    }
})
// from vuex store
const actions = {  
  async userRefresh({ commit }) {
    const response = await axios.post(`/token/refresh`,'test')
    commit('REFRESH_USER', response.data)
  },
const mutations = {  
  REFRESH_USER: (state, resp) =>{
    state.jwt.access_token = resp.access_token
    localStorage.setItem('access_token',resp.access_token)
    state.jwt.refresh_token = resp.refresh_token
    localStorage.setItem('refresh_token',resp.refresh_token)
  },

Следующий вопрос: можно ли отправить действие vuex из того места, где я хотел бы его отправить?

Это мой первый проект такого рода, но я прошу прощения за свое невежество.

Спасибо!

...