附加所有axios请求的Authorization标头

aww*_*ter 71 reactjs redux axios

我有一个react/redux应用程序从api服务器获取令牌.在用户进行身份验证之后,我想让所有axios请求都将该令牌作为Authorization标头,而不必手动将其附加到操作中的每个请求.我是新手反应/ redux并不确定最好的方法,并没有在谷歌上找到任何质量点击.

这是我的redux设置:

// actions.js
import axios from 'axios';

export function loginUser(props) {
  const url = `https://api.mydomain.com/login/`;
  const { email, password } = props;
  const request = axios.post(url, { email, password });

  return {
    type: LOGIN_USER,
    payload: request
  };
}

export function fetchPages() {
  /* here is where I'd like the header to be attached automatically if the user
     has logged in */ 
  const request = axios.get(PAGES_URL);

  return {
    type: FETCH_PAGES,
    payload: request
  };
}

// reducers.js
const initialState = {
  isAuthenticated: false,
  token: null
};

export default (state = initialState, action) => {
  switch(action.type) {
    case LOGIN_USER:
      // here is where I believe I should be attaching the header to all axios requests.
      return {
        token: action.payload.data.key,
        isAuthenticated: true
      };
    case LOGOUT_USER:
      // i would remove the header from all axios requests here.
      return initialState;
    default:
      return state;
  }
}
Run Code Online (Sandbox Code Playgroud)

我的令牌存储在redux store下state.session.token.

我对如何继续有点迷茫.我已经尝试在我的根目录中的文件中创建一个axios实例并更新/导入而不是从node_modules,但是当状态改变时它没有附加头.任何反馈/想法都非常感谢,谢谢.

Har*_*dha 104

文档axios可以看到有一种机制可供您设置默认标头,该标头将随您发出的每个请求一起发送.

// Add a request interceptor
axios.interceptors.request.use(function (config) {
    const token = store.getState().session.token;
    config.headers.Authorization =  token;

    return config;
});
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下:

axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
Run Code Online (Sandbox Code Playgroud)

如果需要,您可以创建一个自执行功能,当商店中存在令牌时,该功能将设置授权标头.

axios.defaults.headers.common['Authorization'] = store.getState().session.token;
Run Code Online (Sandbox Code Playgroud)

现在,您不再需要手动将令牌附加到每个请求.您可以将上述功能放在保证每次执行的文件中(例如:包含路径的文件).

希望能帮助到你 :)

  • @HardikModha我很好奇如何用Fetch API做到这一点. (4认同)
  • @awwester 您不需要中间件来在标头中附加令牌。在标头中附加令牌是 `axios.defaults.header.common[Auth_Token] = token` 就这么简单。 (3认同)
  • 嗨@HardikModha。如果我在想要更新令牌时使用设置的令牌的默认标头,则无法再次将其设置到标头中。这是对的吗?所以我必须使用拦截器。 (2认同)
  • 一个小问题:如果您遵循第二种方法,则必须分别为应用程序中的每个 Axios 实例设置默认标头。这花了我一段时间才弄清楚。 (2认同)

Kma*_*hta 41

对我来说,最好的解决方案是创建一个客户端服务,您将使用它来实例化其令牌axios.

import axios from 'axios';

const client = (token = null) => {
    const defaultOptions = {
        headers: {
            Authorization: token ? `Token ${token}` : '',
        },
    };

    return {
        get: (url, options = {}) => axios.get(url, { ...defaultOptions, ...options }),
        post: (url, data, options = {}) => axios.post(url, data, { ...defaultOptions, ...options }),
        put: (url, data, options = {}) => axios.put(url, data, { ...defaultOptions, ...options }),
        delete: (url, options = {}) => axios.delete(url, { ...defaultOptions, ...options }),
    };
};

const request = client('MY SECRET TOKEN');

request.get(PAGES_URL);
Run Code Online (Sandbox Code Playgroud)

在此客户端中,您还可以根据需要从localStorage/cookie中检索令牌.

  • 如果您想使用“应用程序类型”标头进行 request.get() 该怎么办?通过您的方法,defaultOptions 中的标头将被请求中的标头覆盖。我是对的?谢谢。 (2认同)

lli*_*oor 35

如果您使用"axios":"^ 0.17.1"版本,您可以这样做:

创建axios实例:

// Default config options
  const defaultOptions = {
    baseURL: <CHANGE-TO-URL>,
    headers: {
      'Content-Type': 'application/json',
    },
  };

  // Create instance
  let instance = axios.create(defaultOptions);

  // Set the AUTH token for any request
  instance.interceptors.request.use(function (config) {
    const token = localStorage.getItem('token');
    config.headers.Authorization =  token ? `Bearer ${token}` : '';
    return config;
  });
Run Code Online (Sandbox Code Playgroud)

然后,对于任何请求,将从localStorage中选择令牌,并将其添加到请求标头中.

我使用此代码在整个应用程序中使用相同的实例:

import axios from 'axios';

const fetchClient = () => {
  const defaultOptions = {
    baseURL: process.env.REACT_APP_API_PATH,
    method: 'get',
    headers: {
      'Content-Type': 'application/json',
    },
  };

  // Create instance
  let instance = axios.create(defaultOptions);

  // Set the AUTH token for any request
  instance.interceptors.request.use(function (config) {
    const token = localStorage.getItem('token');
    config.headers.Authorization =  token ? `Bearer ${token}` : '';
    return config;
  });

  return instance;
};

export default fetchClient();
Run Code Online (Sandbox Code Playgroud)

祝好运.


elQ*_*aba 7

同样,我们有一个函数可以从以下调用中设置或删除令牌:

import axios from 'axios';

export default function setAuthToken(token) {
  axios.defaults.headers.common['Authorization'] = '';
  delete axios.defaults.headers.common['Authorization'];

  if (token) {
    axios.defaults.headers.common['Authorization'] = `${token}`;
  }
}
Run Code Online (Sandbox Code Playgroud)

我们总是在初始化时清除现有令牌,然后建立接收到的令牌。


Pau*_*. B 5

如果您想在将来调用其他 api 路由并将您的令牌保留在商店中,请尝试使用 redux middleware

中间件可以侦听 api 操作并相应地通过 axios 分派 api 请求。

这是一个非常基本的例子:

动作/api.js

export const CALL_API = 'CALL_API';

function onSuccess(payload) {
  return {
    type: 'SUCCESS',
    payload
  };
}

function onError(payload) {
  return {
    type: 'ERROR',
    payload,
    error: true
  };
}

export function apiLogin(credentials) {
  return {
    onSuccess,
    onError,
    type: CALL_API,
    params: { ...credentials },
    method: 'post',
    url: 'login'
  };
}
Run Code Online (Sandbox Code Playgroud)

中间件/api.js

import axios from 'axios';
import { CALL_API } from '../actions/api';

export default ({ getState, dispatch }) => next => async action => {
  // Ignore anything that's not calling the api
  if (action.type !== CALL_API) {
    return next(action);
  }

  // Grab the token from state
  const { token } = getState().session;

  // Format the request and attach the token.
  const { method, onSuccess, onError, params, url } = action;

  const defaultOptions = {
    headers: {
      Authorization: token ? `Token ${token}` : '',
    }
  };

  const options = {
    ...defaultOptions,
    ...params
  };

  try {
    const response = await axios[method](url, options);
    dispatch(onSuccess(response.data));
  } catch (error) {
    dispatch(onError(error.data));
  }

  return next(action);
};
Run Code Online (Sandbox Code Playgroud)


jam*_*ace 5

重点是为每个请求在拦截器上设置令牌

import axios from "axios";
    
const httpClient = axios.create({
    baseURL: "http://youradress",
    // baseURL: process.env.APP_API_BASE_URL,
});

httpClient.interceptors.request.use(function (config) {
    const token = localStorage.getItem('token');
    config.headers.Authorization =  token ? `Bearer ${token}` : '';
    return config;
});
Run Code Online (Sandbox Code Playgroud)