检索JWT令牌后,请求失败

时间:2019-02-02 17:43:34

标签: django-rest-framework jwt axios

我正在将Django JWT与DRF和Vue Js与axios一起使用。当我在用户登录检索和存储在其中,我已经验证工作本地存储的令牌。然后,我重定向到一个新页面,在此我再次提出获取数据的请求。每次我重定向到这个页面,我得到一个401没有授权,当我刷新页面,它工作正常。我检查,以确保令牌使这是第二个请求之前存储。我试图得到重定向的页面上创建挂钩的数据。我还创建了一个axios实例来处理标头,并使用基本路由,然后将其导入到需要的文件中,我不确定是否与此有关。当令牌已过期,您尝试检索一个新的,这也只是发生。我应该是刷新而不是试图获得一个新的令牌?

Axios实例

import axios from 'axios'

export default axios.create({
  baseURL: `http://127.0.0.1:8000/`,
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'JWT ' + localStorage.getItem('token')
  },
  xsrfCookieName: 'csrftoken',
  xsrfHeaderName: 'X-CSRFToken',
  withCredentials: true
})

编辑

api.js

import axios from 'axios'

export default axios.create({
  baseURL: `http://127.0.0.1:8000/`,
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'JWT ' + localStorage.getItem('token')
  },
  xsrfCookieName: 'csrftoken',
  xsrfHeaderName: 'X-CSRFToken',
  withCredentials: true
})

AppLogin.vue

通过单击登录按钮触发确认

 confirm: function() {
       API.post("accounts/login/", {
        email: this.email,
        password: this.password,
       })
        .then(result => {
          console.log(result.data.token);
          this.token = result.data.token;
          localStorage.setItem("token", this.token);
          this.getUserInfo()
        })
        .catch(error => {
          console.log(error);
        });

    },
    getUserInfo: function(){
      axios.get("http://127.0.0.1:8000/userinfo/get/", {
        headers: {
          'Content-Type': 'application/json',
          Authorization: 'JWT ' + this.token
        }
      })
        .then(response => {
          console.log(response.data.pos);
          var pos = response.data.pos;
          this.reroute(pos);
        })
        .catch(error => {
          console.log(error);
        });
    },
    reroute(pos) {
      if (pos == "owner") {
        this.$router.push({ path: "/bizhome" });
      } else {
        this.$router.push({ path: "/" });
      }
    }

BizHome.vue

这是在网页该登录重定向到成功

created: function() {
    this.getLocations();
  },
  methods: {
    getLocations() {
      API.get("business/")
        .then(response => {
          this.biz = response.data;
        })
        .catch(error => {
          console.log(error);
        });

      API.get("locations/")
        .then(response => {
          this.bizLocations = response.data;
        })
        .catch(error => {
          console.log(error);
        });
    },
  }

解决方案

使用下面从YuuwakU获得的一些建议,我将标头直接添加到getLocations方法中的get调用中,以覆盖axios实例标头。在实例中更新令牌之前,似乎已加载了新页面。一个缺点是该解决方案是,虽然我现在已经直接头添加到所有我打的电话。在实例中的头再也没有更新。在成功检索令牌后,我确实向确认方法中添加了API.defaults.headers.common['Authorization'] = 'JWT ' + result.data.token;,该令牌应该已经为实例更新了令牌。这并没有为我工作,如果任何人有任何想法,我会有兴趣听他们

编辑2

我确实弄清楚了axios实例为什么不更新它的原因,是因为我试图从api.js中的本地存储中获取令牌,并且它被覆盖了。现在它可以工作了,但令牌不是永久的,因此也不理想。如果我找到一个更好的解决方案,我会更新。

最终更新

我终于找到了一个好的解决方案。我从api.js中的axios实例中删除了授权标头,然后从所有axios调用中删除了所有标头。在成功登录后的确认方法中,我添加了前面提到的API.defaults.headers.common['Authorization'] = 'JWT ' + result.data.token;这一行,还将令牌添加到了本地存储中。我有一个验证令牌方法在页面加载之前运行。在该方法之前,我使POST请求来验证添加的令牌I API.defaults.headers.common['Authorization'] = 'JWT ' + localstorage.getItem('token');。这允许用户导航离开站点并返回,如果有效,仍然使用令牌,并且不需要在每次调用时都设置标头。

1 个答案:

答案 0 :(得分:0)

发生这种情况的原因是因为已经使用本地存储中存在的过期令牌创建了axios实例。所以,你必须确保做出了爱可信实例与登录后的令牌的新鲜得到更新,否则你最终会使用旧的令牌,直到一个新的页面重新加载。请尝试以下操作:

import axios from 'axios'

export default axios.create({
  baseURL: `http://127.0.0.1:8000/`,
  headers: {
    'Content-Type': 'application/json',
    Authorization() { // Converted to a method, similar concept to a vue data property
      return `JWT  ${localStorage.getItem('token')}`,
    }
  },
  xsrfCookieName: 'csrftoken',
  xsrfHeaderName: 'X-CSRFToken',
  withCredentials: true
})

或者,您甚至还可以使用axios拦截器从每个请求中从localStorage获取:

// Add a request interceptor
axios.interceptors.request.use(config => {
    // Do something before request is sent
    config.headers = {
      'Content-Type': 'application/json',
      Authorization: 'JWT ' + localStorage.getItem('token')
    }
    return config
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });