在React.js中刷新页面后清除Axios默认标头

时间:2019-02-11 18:41:44

标签: reactjs axios

我在Login组件中设置axios.defaults.headers.Authorization = MY_TOKEN,该组件在Authentication组件中呈现,该组件检查this.state.loggedin是否设置为true。如果为false,则呈现Login组件;如果为true,则使用BrowserRouter呈现UserComponent。 BrowserRouter读取“ /”路径并导航到Documents组件。在此导航页面期间,刷新并清除axios.defaults.headers.Authorization,返回未定义的值。即使刷新页面,如何保存axios.defaults.headers?还是应该在路由器每次导航到其他组件时初始化默认标头?

更新

添加了一些代码,如何在Authentication.js中呈现

      render() {
      return (
        <UserNavigationContainer
          {...this.props}
          logout={this.onClickLogoutHandler}
        />
      );
     }

UserNavigationContainer.js渲染溃败(代码不完整)

<BrowserRouter>
      <div>
        <UserNavigationComponent {...this.props}>
          <Switch>
            <Route
              exact
              path="/"
              component={UserSubmittedDocumentsContainer}
            />

实际上,当呈现UserNavigationContainer时,它导航到“ /”并在导航时刷新页面。

3 个答案:

答案 0 :(得分:1)

我也有类似的经历,这就是我能够解决的方法

在用户登录/注册后将令牌保留在本地存储中: 第一步是在登录/注册成功后将用户令牌保留在本地存储中,您可以在浏览器的本地存储API here

上进行读取

移动将“授权标头”设置为始终呈现而不考虑当前路径的组件的逻辑(在我的情况下为导航栏组件): 接下来是将负责设置Authorization标头的逻辑移到我的导航栏组件中,这样做,它会自动从本地存储中获取活动用户的令牌并设置授权标头。现在,无论react-router呈现的组件是什么,都将不断设置授权标头,从而避免了其他每个组件都需要这样做。

PS :移动逻辑并不会阻止您最初在登录组件内部设置授权标头,它仅解决了对要渲染的每个其他组件这样做的问题。

答案 1 :(得分:1)

我遇到了同样的问题。我通过在根文件中设置请求通用标头解决了我的问题。就我而言,它是index.js。

setting request headers common globally

您是否注意到我正在从localStorage设置app_token?

最初,AuthLayout呈现登录组件。如果登录成功,我必须重定向到管理路由。

Auth.js

Login component

因此,我计划在登录组件中设置标题。如果登录成功,我可以在请求标头中设置app_token。一切顺利,直到我刷新页面。

Login.js

setting app_token from response

因此,我在localStorage中设置了令牌,并在index.js中使用了它来全局设置标头。

Login.js

setting localstorage

我想这不是更好的解决方案。好吧,即使页面刷新后,我也可以全局设置标题并使用令牌进行身份验证。

更新:

在标头中设置授权的另一种简单解决方案是使用拦截器。

第1步:创建一个名为interceptor.js的文件。创建一个实例。

const axios = require("axios");
const axiosApiInstance = axios.create();

// Request interceptor for API calls
axiosApiInstance.interceptors.request.use(
  async (config) => {
    config.headers = {
      Authorization: `Bearer ${localStorage.getItem("token")}`,
    };
    return config;
  },
  (error) => {
    Promise.reject(error);
  }
);

export default axiosApiInstance;

第2步:调用需要授权标头的后续API,如下所述。

import axiosApiInstance from "./interceptor";

let response = await axiosApiInstance.get(
      "/api/***"
    );
    return response;

谢谢

答案 2 :(得分:0)

达马利的答案很正确,但我也认为值得对此进行扩展:

移动将Authorization标头设置为始终存在的组件的逻辑 不管当前路径如何渲染

说实话,很难理解OP的项目结构,因为出于某种原因发布的摘录与auth-routing逻辑有关,这不是要问的问题。但是,为清楚起见,请详细说明以上引用:

所有身份验证逻辑,包括设置axios标头,都应封装在单个组件中(可能是React Context)。它不像“设置标题并传递go”那样简单:任何生产级应用程序都需要:

  • 保持某些身份验证状态(已登录/注销?)
  • 经常评估该状态(过期?)
  • 也许维护和评估更详细的登录信息(例如角色)
  • 根据上述内容处理路由和API请求

这是身份验证模块的角色。

auth模块应控制axios身份验证标头。这意味着我们几乎可以肯定地说的是两个单独的模块:

  1. HTTPs服务模块(包含和导出axios实例),并且
  2. 身份验证模块

现在:正如OP所观察到的或多或少:如果auth模块只是调用axios实例并在登录时对其应用标头,则刷新后将不会持续。

Damali答案的麻烦在于即使始终渲染您的身份验证模块(例如,它位于应用程序的顶部),axios配置仍然无法在页面刷新时保持不变。页面刷新将强制重新渲染:标题将消失。

答案看似简单:每次需要身份验证时(以及登录时)重新应用标头。有很多方法可以做到这一点,这里仅是一种:

// apiService.js
import Axios from 'axios';
const axios = Axios.create();

export function setDefaultHeader(key, value){
    axios.defaults.headers.common[key] = value;
}
export axios;


// auth.js
import { axios, setDefaultHeader } from '../services/apiService.js';

const tokenKey = 'x-auth-token';
setDefaultHeader(tokenKey, localStorage[tokenKey]);