Axios: 在每个请求上更新身份验证标头?

创建于 2018-02-25  ·  10评论  ·  资料来源: axios/axios

大家好,

我创建了一个用于受保护 api 资源的 axios 新实例,并在其上附加了带有令牌的 auth 标头,但问题是如果我转到控制台并从 localStorage 中删除令牌,axios 仍将其作为实例发送没有更新。

是否有解决方案,以便实例中的身份验证标头可以在每个请求中检查 localStorage 中的令牌?

谢谢!

最有用的评论

为此,我使用了拦截器。 如果请求的基本 URL 是我的 API,我会添加 auth 标头(以防止将凭据发送给第三方)。 这是在每个请求上运行的,因此如果令牌更改(例如由于令牌刷新),则下一个请求将获取新令牌。 我还确保我检查请求中的现有值,以允许覆盖来自调用站点的标头,如果由于某种原因发生这种情况是必要的。

axios.interceptors.request.use(
  config => {
    if (config.baseURL === baseApiAddress && !config.headers.Authorization) {
      const token = getToken();

      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }
    }

    return config;
  },
  error => Promise.reject(error)
);

所有10条评论

我有一个类似的用例,如果每个请求都懒惰地评估传递的标头,那就太好了。

想法:
与其急切地将标头散列作为对象( axios.create({headers: {...}})传递,我们可以传递一个返回标头( axios.create({headers: () => {...}} )的函数,该函数将在发送请求之前进行评估。

你怎么认为?
编辑:这是一个提议,我认为目前这行不通。

我遇到了同样的用例。 我在短期内最终做的是使用transformRequest函数。 绝对是一个黑客,很乐意帮助在代码库中实施适当的延迟加载方法。

请参阅下面的代码片段。 auth()获取登录用户的令牌(如果可用)。

let HTTP = axios.create({
  baseURL: baseurl,
  transformRequest: [function (data, headers) {
    headers['Authorization'] = auth()
    return JSON.stringify(data)
  }],
  headers: {
    'Content-Type': 'application/json'
  }
})

为此,我使用了拦截器。 如果请求的基本 URL 是我的 API,我会添加 auth 标头(以防止将凭据发送给第三方)。 这是在每个请求上运行的,因此如果令牌更改(例如由于令牌刷新),则下一个请求将获取新令牌。 我还确保我检查请求中的现有值,以允许覆盖来自调用站点的标头,如果由于某种原因发生这种情况是必要的。

axios.interceptors.request.use(
  config => {
    if (config.baseURL === baseApiAddress && !config.headers.Authorization) {
      const token = getToken();

      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }
    }

    return config;
  },
  error => Promise.reject(error)
);

@mattstrayer你能告诉我

我结束了这个。

axios.create({
  baseURL: '<your-api>',
  headers: {
    Authorization: {
      toString () {
        return `Bearer ${localStorage.getItem('token')}`
      }
    }
  }
})

我不确定它是否适用于任何情况。

我的http.js文件:

import axios from 'axios';
import {store} from './store';

const http = axios.create ({
  baseURL: process.env.VUE_APP_ROOT_API,
  timeout: 1000,
  headers: {'Content-Type': 'application/json'},
});

http.interceptors.request.use (
  function (config) {
    const token = store.token;
    if (token) config.headers.Authorization = `Bearer ${token}`;
    return config;
  },
  function (error) {
    return Promise.reject (error);
  }
);

export default http;

我的商店,一个简单的获取/设置“类”

export const store = {
    _username: '',
    _email: '',
    _token: '',

    isLogged () {
      return this.token
    },

    set username (str) {
      this._username = str
      localStorage.setItem('username',str)
    },
    get username () {
      return this._username || localStorage.getItem('username')
    },

    set email (str) {
      this._email = str
      localStorage.setItem('email',str)
    },
    get email () {
      return this._email || localStorage.getItem('email')
    },

    set token (str) {
      this._token = str
      localStorage.setItem('token',str)
    },
    get token () {
      return this._token || localStorage.getItem('token')
    }

  }

我的用户服务“类”:

import http from './http'

export const user = {
  ping: () => http.get('/users/ping'),
  save: (user) => http.post('/users', user)
}

最后,我的实现:

import {user} from '@/services'

 user.ping().then( r => {
      console.log(r.data)
    })

顺便说一句, process.env.VUE_APP_ROOT_API@/services是 Vue 的东西......

结果:
image

@danielschmitz谢谢你的例子!!

看起来你们都想通了,这不是错误,所以我要关闭它了🙂

我发现将拦截器包装在 async/await 中以确保在触发 API 调用之前设置我的令牌很有用:

http.interceptors.request.use (
  async (config) => {
    const token = await getToken(); // slightly longer running function than example above
    if (token) config.headers.Authorization = `Bearer ${token}`;
    return config;
  },
  (error) => {
    return Promise.reject (error);
  }
);

为此,我使用了拦截器。 如果请求的基本 URL 是我的 API,我会添加 auth 标头(以防止将凭据发送给第三方)。 这是在每个请求上运行的,因此如果令牌更改(例如由于令牌刷新),则下一个请求将获取新令牌。 我还确保我检查请求中的现有值,以允许覆盖来自调用站点的标头,如果由于某种原因发生这种情况是必要的。

axios.interceptors.request.use(
  config => {
    if (config.baseURL === baseApiAddress && !config.headers.Authorization) {
      const token = getToken();

      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }
    }

    return config;
  },
  error => Promise.reject(error)
);

拦截器似乎是最优雅的解决方案

此页面是否有帮助?
0 / 5 - 0 等级