Прикрепить заголовок авторизации для всех запросов на аксиомы
У меня есть приложение реакции/сокращения, которое извлекает токен с сервера api. После аутентификации пользователя я хотел бы, чтобы все запросы axios имели этот токен в качестве заголовка авторизации без необходимости вручную привязывать его к каждому запросу в действии. Я новичок в реагировании/сокращении и не уверен в лучшем подходе и не нахожу качественных хитов в Google.
Вот моя установка 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;
}
}
Мой токен хранится в магазине redux под state.session.token
.
Я немного потерял, как продолжить. Я попытался сделать экземпляр axios в файле в корневом каталоге и обновить/импортировать, а не из node_modules, но он не прикрепляет заголовок при изменении состояния. Любые отзывы/идеи очень ценятся, спасибо.
Ответы
Ответ 1
Есть несколько способов достичь этого. Здесь я объяснил два наиболее распространенных подхода.
1. Вы можете использовать перехватчики axios для перехвата любых запросов и добавления заголовков авторизации.
// Add a request interceptor
axios.interceptors.request.use(function (config) {
const token = store.getState().session.token;
config.headers.Authorization = token;
return config;
});
2. Из документации axios
вы можете увидеть, что есть механизм, который позволяет вам установить заголовок по умолчанию, который будет отправляться при каждом вашем запросе.
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
Итак, в вашем случае:
axios.defaults.headers.common['Authorization'] = store.getState().session.token;
Если вы хотите, вы можете создать самовыполняющуюся функцию, которая сама установит заголовок авторизации, когда токен присутствует в хранилище.
(function() {
String token = store.getState().session.token;
if (token) {
axios.defaults.headers.common['Authorization'] = token;
} else {
axios.defaults.headers.common['Authorization'] = null;
/*if setting null does not remove 'Authorization' header then try
delete axios.defaults.headers.common['Authorization'];
*/
}
})();
Теперь вам больше не нужно прикреплять токен вручную к каждому запросу. Вы можете поместить вышеупомянутую функцию в файл, который гарантированно будет выполняться каждый раз (например: Файл, который содержит маршруты).
Надеюсь, поможет :)
Ответ 2
Лучшим решением для меня является создание клиентской службы, которую вы создадите с помощью токена, чтобы использовать его для переноса 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);
В этом клиенте вы также можете извлечь токен из localStorage/cookie, как вы хотите.
Ответ 3
Если вы используете "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;
});
Затем для любого запроса токен будет выбран из 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();
Удачи.
Ответ 4
Аналогично, у нас есть функция для установки или удаления токена из таких вызовов:
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}`;
}
}
Мы всегда очищаем существующий токен при инициализации, затем устанавливаем полученный.
Ответ 5
Если вы хотите называть другие маршруты api в будущем и сохранить свой токен в магазине, попробуйте использовать промежуточное программное обеспечение redux.
Среднее программное обеспечение может прослушивать действие api и отправлять запросы 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'
};
}
промежуточного слоя /api.js
import axios from 'axios';
import { CALL_API } from '../actions/api';
export default ({ getState, dispatch }) => next => async action => {
// Ignore anything that 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);
};
Ответ 6
Иногда возникает случай, когда некоторые запросы, сделанные с помощью axios, указывают на конечные точки, которые не принимают заголовки авторизации. Таким образом, альтернативный способ установить заголовок авторизации только на разрешенном домене такой же, как в примере ниже. Поместите следующую функцию в любой файл, который выполняется каждый раз при запуске приложения React, например в файле маршрутов.
export default () => {
axios.interceptors.request.use(function (requestConfig) {
if (requestConfig.url.indexOf(<ALLOWED_DOMAIN>) > -1) {
const token = localStorage.token;
requestConfig.headers['Authorization'] = 'Bearer ${token}';
}
return requestConfig;
}, function (error) {
return Promise.reject(error);
});
}