使用flask-cors处理axios响应拦截器以刷新jwt令牌

时间:2019-11-09 12:51:14

标签: flask cors jwt axios flask-restful

我将使用flask-restful和jwt令牌来构建api,以使用axios进行请求以通过vue前端进行授权。请求正常工作,并且jwt_required和jwt_refresh_token标记到目前为止正常工作。我可以登录,我可以拉数据,等等,没有问题。我遇到的问题是,我希望用户在尝试发出请求时刷新其令牌,并且由于访问令牌过期而发生状态401未经授权的错误。错误以字符串形式返回,而不是实际错误,因此刷新令牌和更新标头后,我无法检查“ error.status”或获取“ error.config”来重新提交失败的请求。我不认为这是一个axios问题,我认为这是一个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动作?

这是我的第一个具有Vue的项目,所以我为自己的无知表示歉意。

谢谢!

0 个答案:

没有答案