所以防范伪造请求的关键就是检查请求泉源,refferer 字段虽然可以标识当前站点,但是不敷可靠,如今业界比力通用的解决方案照旧在每个请求上附带一个 anti-CSRF token,这个的原理是攻击者无法拿到 Cookie,所以我们可以通过对 Cookie 进行加密(比如对 sid 进行加密),然后配合服务端做一些简单的验证,就可以判定当前请求是不是伪造的。
Axios 简单地实现了对特殊 csrf token 的支持,
// Add xsrf header
// This is only done if running in a standard browser environment.
// Specifically not if we’re in a web worker, or react-native.
if (utils.isStandardBrowserEnv()) {
// Add xsrf header
var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ?
cookies.read(config.xsrfCookieName) :
undefined;
if (xsrfValue) {
requestHeaders[config.xsrfHeaderName] = xsrfValue;
}
}
Interceptor
拦截器是 Axios 的一个特色 Feature,我们先简单回首下使用方式,
// 拦截器可以拦截请求或响应
// 拦截器的回调将在请求或响应的 then 或 catch 回调前被调用
var instance = axios.create(options);
var requestInterceptor = axios.interceptors.request.use(
(config) => {
// do something before request is sent
return config;
},
(err) => {
// do somthing with request error
return Promise.reject(err);
}
);
// 移除已设置的拦截器
axios.interceptors.request.eject(requestInterceptor)
那么拦截器是怎么实现的呢?
定位到源码 lib/core/Axios.js 第 14 行,
function Axios(instanceConfig) {
this.defaults = instanceConfig;
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}
通过 Axios 的构造函数可以看到,拦截器 interceptors 中的 request 和 response 两者都是一个叫做 InterceptorManager 的实例,这个 InterceptorManager 是什么?
定位到源码 lib/core/InterceptorManager.js,
function InterceptorManager() {
this.handlers = [];
}
InterceptorManager.prototype.use = function use(fulfilled, rejected, options) {
this.handlers.push({
fulfilled: fulfilled,
rejected: rejected,
synchronous: options ? options.synchronous : false,
runWhen: options ? options.runWhen : null
});
return this.handlers.length - 1;
};
InterceptorManager.prototype.eject = function eject(id) {
if (this.handlers[id]) {
this.handlers[id] = null;
}
};
InterceptorManager.prototype.forEach = function forEach(fn) {
utils.forEach(this.handlers, function forEachHandler(h) {
if (h !== null) {
fn(h);
}
});
};
InterceptorManager 是一个简单的变乱管理器,实现了对拦截器的管理,
通过 handlers 存储拦截器,然后提供了添加,移除,遍历执行拦截器的实例方法,存储的每一个拦截器对象都包含了作为 Promise 中 resolve 和 reject 的回调以及两个配置项。
值得一提的是,移除方法是通过直接将拦截器对象设置为 null 实现的,而不是 splice 剪切数组,遍历方法中也增加了相应的 null 值处置惩罚。如许做一方面使得每一项ID保持为项的数组索引不变,另一方面也避免了重新剪切拼接数组的性能损失。
拦截器的回调会在请求或响应的 then 或 catch 回调前被调用,这是怎么实现的呢?
回到源码 lib/core/Axios.js 中第 27 行,Axios 实例对象的 request 方法,
我们提取其中的关键逻辑如下,
Axios.prototype.request = function request(config) {
// Get merged config
// Set config.method
// …
var requestInterceptorChain = [];
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
});
var responseInterceptorChain = [];
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
});
var promise;
var chain = [dispatchRequest, undefined];
Array.prototype.unshift.apply(chain, requestInterceptorChain);
chain.concat(responseInterceptorChain);
promise = Promise.resolve(config);
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
};
可以看到,当执行 request 时,实际的请求(dispatchRequest)和拦截器是通过一个叫 chain 的队列来管理的。整个请求的逻辑如下,
- 首先初始化请求和响应的拦截器队列,将 resolve,reject 回调依次放入队头
- 然后初始化一个 Promise 用来执行回调,chain 用来存储和管理实际请求和拦截器
- 将请求拦截器放入 chain 队头,响应拦截器放入 chain 队尾
- 队列不为空时,通过 Promise.then 的链式调用,依次将请求拦截器,实际请求,响应拦截器出队
- 最后返回链式调用后的 Promise
这里的实际请求是对适配器的封装,请求和响应数据的转换都在这里完成。
那么数据转换是怎样实现的呢?
Transform data
定位到源码 lib/core/dispatchRequest.js,
function dispatchRequest(config) {
throwIfCancellationRequested(config);
// Transform request data
config.data = transformData(
config.data,
config.headers,
config.transformRequest
);
var adapter = config.adapter || defaults.adapter;
return adapter(config).then(function onAdapterResolution(response) {
throwIfCancellationRequested(config);
// Transform response data
response.data = transformData(
response.data,
response.headers,
config.transformResponse
);
return response;
}, function onAdapterRejection(reason) {
if (!isCancel(reason)) {
throwIfCancellationRequested(config);
// Transform response data
if (reason && reason.response) {
reason.response.data = transformData(
reason.response.data,
reason.response.headers,
config.transformResponse
);
}
}
return Promise.reject(reason);
});
};
这里的 throwIfCancellationRequested 方法用于取消请求,关于取消请求稍后我们再讨论,可以看到发送请求是通过调用适配器实现的,在调用前和调用后会对请求和响应数据进行转换。
转换通过 transformData 函数实现,它会遍历调用设置的转换函数,转换函数将 headers 作为第二个参数,所以我们可以根据 headers 中的信息来执行一些不同的转换操作,
// 源码 core/transformData.js
function transformData(data, headers, fns) {
utils.forEach(fns, function transform(fn) {
data = fn(data, headers);
});
return data;
};
Axios 也提供了两个默认的转换函数,用于对请求和响应数据进行转换。默认情况下,
Axios 会对请求传入的 data 做一些处置惩罚,比如请求数据如果是对象,会序列化为 JSON 字符串,响应数据如果是 JSON 字符串,会实验转换为 JavaScript 对象,这些都是非常实用的功能,
对应的转换器源码可以在 lib/default.js 的第 31 行找到,
var defaults = {
// Line 31
transformRequest: [function transformRequest(data, headers) {
normalizeHeaderName(headers, ‘Accept’);
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里不停到如今。
深知大多数前端工程师,想要提拔技能,每每是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术故步自封!
因此网络整理了一份《2024年Web前端开发全套学习资料》,初志也很简单,就是希望能够帮助到想自学提拔又不知道该从何学起的朋侪,同时减轻大家的负担。
既有得当小白学习的零基础资料,也有得当3年以上经验的小同伴深入学习提拔的进阶课程,根本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比力大,这里只是将部分目次大纲截图出来,每个节点内里都包含大厂面经、学习条记、源码讲义、实战项目、讲解视频,而且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
文末
技术是没有终点的,也是学不完的,最告急的是活着、不秃。
零基础入门的时候看书照旧看视频,我觉得成年人,何必做选择题呢,两个都要。喜欢看书就看书,喜欢看视频就看视频。
最告急的是在自学的过程中,肯定不要眼高手低,要实战,把学到的技术投入到项目当中,解决题目,之后进一步锻炼自己的技术。
自学最怕的就是缺乏自驱力,肯定要自律,杜绝“三天打鱼两天晒网”,到最后白忙活一场。
高度自律的同时,要保持耐心,不抛弃不放弃,切勿自怨自艾,每天给自己一点点鼓励,学习的劲头就会很足,不轻易犯困。
技术学到手后,找工作的时候肯定要好好准备一份简历,不要无头苍蝇一样去海投简历,轻易“竹篮打水一场空”。好好的准备一下简历,毕竟是找工作的敲门砖。
拿到面试约请后,在面试的过程中肯定要大大方方,努力把自己学到的知识舒服地表达出来,不要由于是自学就不敷自大,给面试官一个好的印象,面试乐成的几率就会大很多,加油吧,骚年!
CodeChina开源项目:【大厂前端面试题剖析+核心总结学习条记+真实项目实战+最新讲解视频】
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云盘算、MySQL、PMP、网络安全、Python爬虫、UE5、UI计划、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、盘算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云盘算
准备一下简历,毕竟是找工作的敲门砖。
拿到面试约请后,在面试的过程中肯定要大大方方,努力把自己学到的知识舒服地表达出来,不要由于是自学就不敷自大,给面试官一个好的印象,面试乐成的几率就会大很多,加油吧,骚年!
CodeChina开源项目:【大厂前端面试题剖析+核心总结学习条记+真实项目实战+最新讲解视频】
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云盘算、MySQL、PMP、网络安全、Python爬虫、UE5、UI计划、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、盘算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云盘算
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |