Reactjs 为所有axios请求附加授权标头
我有一个react/redux应用程序,它从api服务器获取令牌。在用户进行身份验证后,我希望所有axios请求都将该令牌作为授权头,而不必手动将其附加到操作中的每个请求。我对react/redux相当陌生,不确定最佳方法,也没有在google上找到任何高质量的点击 以下是我的redux设置:Reactjs 为所有axios请求附加授权标头,reactjs,redux,axios,Reactjs,Redux,Axios,我有一个react/redux应用程序,它从api服务器获取令牌。在用户进行身份验证后,我希望所有axios请求都将该令牌作为授权头,而不必手动将其附加到操作中的每个请求。我对react/redux相当陌生,不确定最佳方法,也没有在google上找到任何高质量的点击 以下是我的redux设置: // actions.js import axios from 'axios'; export function loginUser(props) { const url = `https://ap
// 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存储中的状态.session.token
下
我对如何进行有点迷茫。我尝试在根目录中的文件中创建一个,并更新/导入该文件,而不是从节点_模块进行更新/导入,但当状态更改时,它不会附加头。非常感谢您的任何反馈/想法。对我来说,最好的解决方案是创建一个客户端服务,您将使用令牌实例化该服务,并使用它包装
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中检索令牌。有多种方法可以实现此目的。在这里,我解释了两种最常见的方法 一,。您可以使用拦截任何请求并添加授权标头
// Add a request interceptor
axios.interceptors.request.use(function (config) {
const token = store.getState().session.token;
config.headers.Authorization = token;
return config;
});
二,。从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'];
*/
}
})();
现在,您不再需要手动将令牌附加到每个请求。您可以将上述函数放在保证每次执行的文件中(例如:包含路由的文件)
希望它有帮助:)如果您希望将来调用其他api路由并将令牌保留在应用商店中,请尝试 中间件可以监听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'
};
}
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);
};
中间件/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'
};
}
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);
};
类似地,我们有一个函数来设置或删除调用中的令牌,如下所示:
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}`;
}
}
我们总是在初始化时清理现有令牌,然后建立接收到的令牌。如果使用“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;
});
祝您好运。有时您会遇到这样的情况:使用axios发出的某些请求指向不接受授权头的端点。因此,仅在允许的域上设置授权头的替代方法如下例所示。将以下函数放置在每次React应用程序运行时执行的任何文件中,如routes文件中
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);
});
}
导出默认值()=>{
axios.interceptors.request.use(函数(requestConfig){
if(requestConfig.url.indexOf()>-1){
const token=localStorage.token;
headers['Authorization']='Bearer${token}`;
}
返回requestConfig;
},函数(错误){
返回承诺。拒绝(错误);
});
}
尝试创建新实例,就像我在下面所做的那样
var common_axios = axios.create({
baseURL: 'https://sample.com'
});
// Set default headers to common_axios ( as Instance )
common_axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
// Check your Header
console.log(common_axios.defaults.headers);
如何使用它
common_axios.get(url).......
common_axios.post(url).......
在尝试实现类似的东西时遇到了一些问题,基于这些答案,这就是我想到的。我遇到的问题是:
关键是为每个请求在拦截器上设置令牌
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;
});
从服务器接收令牌后,您将在何处存储授权令牌?localStorage?在redux store会话中。令牌已在使用redux persist,但将查看中间件以在标头中附加令牌,谢谢@awwester您不需要中间件将令牌附加到头中。在标头中附加标记是
axios.defaults.header.common[Auth_token]=token
就这么简单。@HardikModha我很好奇如何使用Fetch API.Hi@HardikModha实现这一点。如果我在更新令牌时使用设置令牌的默认头,则不能将其再次设置到头中。对吗?所以我必须使用拦截器。一个小问题是:如果您使用第二种方法,那么您必须为应用程序中的每个Axios实例分别设置默认头。我花了一段时间才弄明白ễnPhúc很高兴,重点是使用Axiost的“拦截器”。这是最好的答案。。。为每个请求初始化拦截器上的令牌。如果您希望发出带有“应用程序类型”标题的请求,请感谢。使用您的方法,defaultOptions中的标题将被请求中的标题覆盖。我是对的?非常感谢。