localStorage项目未在axios标题中更新

时间:2017-12-08 13:34:00

标签: javascript axios

我正在使用JWT Token身份验证系统,当我登录时,我得到这样的令牌:

axios.post('/login', data)
    .then(response => {
        localStorage.setItem('token', response.data.token);
   });

这很好用,令牌保存在localStorage中。但是,令牌不包含在以后的请求中。 授权标头为Bearer null

这是我设置全局axios对象的方法。

window.axios = axios.create({
    baseURL: '/api/',
    timeout: 10000,
    headers: {
        'X-Requested-With': 'XMLHttpRequest',
        'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content,
        'Authorization': 'Bearer ' + localStorage.getItem('token')
    }
});

如果我刷新网站,则设置标记,并且使用正确。

修改

我通过从Authorization方法移除create()标头,而不是使用window.axios.defaults.headers.common['Authorization']来实现它。但现在 Laravel Echo 会出现同样的问题。我像这样创建实例:

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'xxx',
    cluster: 'eu',
    encrypted: true,
    namespace: 'xxx',
    auth: {
        headers: {
            'Authorization': 'Bearer ' + localStorage.getItem('token')
        }
    }
});

我像这样更新标题:

window.setAuthToken = (token) => {
    window.axios.defaults.headers.Authorization = 'Bearer ' + token;
    window.Echo.options.auth.headers.Authorization = 'Bearer ' + token;
    localStorage.setItem('token', token);
}

axios标头已成功更新,但未成功更新。

3 个答案:

答案 0 :(得分:7)

为此使用axios interceptors。它将在每次请求调用时运行。

与直接在所有组件中使用axios方法相比,更好地将axios方法保存在单独的文件中并对其进行调用。这样,如果需要,我们可以用另一个库替换axios。这就是我在项目中正在做的事情。

import axios from "axios";
import AuthService from "./auth";

import config from '../config'

const instance = axios.create({
  baseURL: config.apiServer.url,
  timeout: config.apiServer.timeout
});

instance.interceptors.request.use(
  config => {
    const token = AuthService.getToken();
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  error => Promise.reject(error)
);

const ApiService = {

  get(url) {
    return instance.get(url)
      .then(res => res)
      .catch(reason => Promise.reject(reason));
  },

  post(url, data) {
    return instance.post(url, data)
      .then(res => res)
      .catch(reason => Promise.reject(reason));
  },

  awaitAll() {
    return axios.all(Array.from(arguments))
      .then(axios.spread((...responses) => responses))
      .catch(reasons => Promise.reject(reasons));
  }

};

export default ApiService;

现在可以在组件中使用它:

ApiService.get(YOUR_GET_URL)
      .then(res => {
        Console.log(res);
      ))
      .catch(reason => {
        console.log(reason);
      })

答案 1 :(得分:3)

问题是您在页面加载时使用localStorage.getItem('token')。当您在localStorage中进行设置时,必须在axios标头中进行更新。

window.axios = axios.create({
    baseURL: '/api/',
    timeout: 10000,
    headers: {
        'X-Requested-With': 'XMLHttpRequest',
        'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content,
        'Authorization': 'Bearer ' + localStorage.getItem('token')
    }
});

axios.post('/login', data)
    .then(response => {
        localStorage.setItem('token', response.data.token);
        window.axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('token');
    });

答案 2 :(得分:2)

我之前遇到过同样的问题,我发现在存储令牌时正在加载包含我的 axios 配置的文件,因此它在存储之前访问了它。

解决方案是,在 axios 配置中:

  const axiosInstance = axios.create({
  baseURL: `${API_BASE_URL}`,
  headers: {
    Accepted: 'appication/json',
    'Content-Type': 'application/json',
  },
});

axiosInstance.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.authorization = token;
    }
    return config;
  },
  (error) => Promise.reject(error),
);

export default axiosInstance;

之后,在需要发出请求的地方使用这个实例。