首页 > 解决方案 > Axios 补丁中使用的不同标头

问题描述

我花了一个小时查看 Chrome 控制台,但看不到这个错误来自哪里。

我正在更新我的 Vue 应用程序中的 OAuth 实现。

故事从socialLink.js发现必须创建新用户开始。Vue 组件 Vue-authentication 取决于access_token响应中的存在,所以我返回一些虚拟文本:

return api.sendResponse(res, { email, name, socialId, access_token: 'abcd' });

库将此值存储在localStorage

本地存储截图

重定向后,SignUp.vue呈现并完成表单。与服务器的第一次通信是创建新用户的 Vuex 调用:

response = await this.$store.dispatch('CREATE_USER_PROFILE', payload);

它返回一个真正短暂的 JWT 令牌:

const token = auth.createToken(userId, nickname, new Date(), null, false, '1m');
return api.sendCreated(res, api.createResponse(token));

之后我将其存储在 Vue 页面中:

const { data } = response;
const token = data.data;
if (token === undefined) {
  this.error = this.$t('sign-up.something-went-wrong');
  return false;
}

我检查了令牌是否包含服务器返回的内容:

Request URL: https://beta.mezinamiridici.cz/api/v1/users
Request Method: POST
Status Code: 201 Created

{"success":true,"data":"eyJhbGciOiJIUzI1NiIs...Tl8JFw2HZ3VMXJk"}

然后我调用另一个 Vuex 方法并传递当前的 JWT 令牌:

await this.$store.dispatch('UPDATE_USER_PROFILE', {

我在 Vuex 开发工具中检查了确实存在正确的 JWT 令牌。然后我将它进一步传递给api.js.

在这里,我创建了一个包含标头的 Axios 配置Authorization

function getAuthHeader(context, jwt = undefined, upload) {
  const config = { headers: { } };
  if (jwt || (context && context.rootState.users.userToken)) {
    config.headers.Authorization = `bearer ${jwt || context.rootState.users.userToken}`;
  }

我再次检查了那里使用了正确的 JWT 令牌。

最后,我将所有数据传递给 Axios:

function patch(endpoint, url, body, context, jwt) {
  const headers = getAuthHeader(context, jwt);
  console.log(headers);
  if (endpoint === 'BFF') {
    return axios.patch(`${VUE_APP_BFF_ENDPOINT}${url}`, body, headers);
  } else {
    return axios.patch(`${VUE_APP_API_ENDPOINT}${url}`, body, headers);
  }
}

我记录并可以确认正确的 JWT 仍然存在:

bearer eyJhbGciOiJIUzI1N....8JFw2HZ3VMXJk

现在没有什么可以将标题更改为abcd,但是,“网络”选项卡显示了它:

网络选项卡屏幕截图

服务器因解析错误而失败。

有没有人知道为什么 Axios 使用的Authorization标头与我传递的值不同?

标签: javascriptvue.jsaxios

解决方案


好的,谜团解开了。vue-authenticate是原因,因为它创建了 Axios 拦截器并Authorization自己处理标头。

vue-authenticate.common.js

var defaultOptions = {
  bindRequestInterceptor: function ($auth) {
    var tokenHeader = $auth.options.tokenHeader;

    $auth.$http.interceptors.request.use(function (config) {
      if ($auth.isAuthenticated()) {
        config.headers[tokenHeader] = [
          $auth.options.tokenType, $auth.getToken()
        ].join(' ');
      } else {
        delete config.headers[tokenHeader];
      }
      return config
    });
  },

我的代码更复杂,它支持带有电子邮件/密码的内部帐户,所以这个代码破坏了我的。拦截器必须存在并且是一个函数,所以解决方案是:

Vue.use(VueAuthenticate, {
  tokenName: 'jwt',
  baseUrl: process.env.VUE_APP_API_ENDPOINT,
  storageType: 'localStorage',
  bindRequestInterceptor() {},
  bindResponseInterceptor() {},
  providers: {
    facebook: {
      clientId: process.env.VUE_APP_FACEBOOK_CLIENT_ID,
      redirectUri: process.env.VUE_APP_FACEBOOK_REDIRECT_URI,
    },

推荐阅读