[油猴脚本开发指南]XHR劫持的第二种格式
# 前言本文来自cxxjackie的代码,进行剖析
来源为
https://bbs.tampermonkey.net.cn/forum.php?mod=viewthread&tid=1062&extra=&page=1
# 开始
其实之前proxy劫持还是相对复杂的,这节课根据cxxjackie的代码我们抄出来一个更简单的劫持方案。
我们先输出一下xhr看看
![图片.png](data/attachment/forum/202111/01/092607u15lm7eli1kesimd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "图片.png")
可以看到xhr的response和responseText等在原型链prototype上
![图片.png](data/attachment/forum/202111/01/092701bg96kzzz336xaxq2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "图片.png")
并且这两个属性都是只有get没有set,代表我们只可以获取他而不可以设置他的内容
所以我们书写代码如下
```javascript
const xhrOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
const xhr = this;
if (arguments == 'xxxxx') {
const getter = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'response').get;
Object.defineProperty(xhr, 'response', {
get: () => {
let result = getter.call(xhr);
//这里可以修改result
return result+'6648848';
}
});
}
return xhrOpen.apply(xhr, arguments);
};
```
首先我们对xhr的open函数进行劫持
```javascript
const xhrOpen = XMLHttpRequest.prototype.open;
```
open是初始化xhr的内容,send是发送数据,这里我们在初始化内容的时候进行劫持。(我们其实可以在任何一个我们满足劫持需求的地方进行劫持)
我们对地址进行判断,如果需要我们进行劫持,则进入劫持
```javascript
const xhr = this;
const getter = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'response').get;
```
这里保存了this到xhr变量,方便接下来的操作
然后获取response的操作符,如果你想要劫持responseText就需要改为responseText
getOwnPropertyDescriptor获取的是一个对象上属性的相关的描述符
可以拿到get set等等。
![图片.png](data/attachment/forum/202111/01/093928mb32q31tody2323i.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "图片.png")
获取到了get描述符我们就可以开始劫持了
```javascript
Object.defineProperty(xhr, 'response', {
get: () => {
let result = getter.call(xhr);
//这里可以修改result
return result+'6648848';
}
});
```
这里对xhr的response属性做了一个defineProperty,当触发xhr.response的时候会访问对应的get,而get调用我们之前获取的getter函数,注意修改this指向,获取原返回内容,进行一定的修改,返回新的修改内容
## 为什么设置到xhr上而不是xhr的原型链上
因为这样可以形成对某一个xhr进行劫持,如果设置到原型链上相当于对所有的xhr进行了一次劫持,如果你的劫持get内有大量的回调代码会严重拖慢运行的速度
## 为什么我没有对原型链的response进行劫持,却成功劫持了?
因为查找response的属性的时候是按顺序查找的,首先在xhr上查找是否有response,然后在xhr的__proto__也就是构造函数的prototype上查找response属性,如果找不到就一层一层往上找,这里我们进行了劫持之后会直接在xhr自身找到,甚至不会找到xhr的__proto__上的response。
# 代码
那么我们最后回忆一下代码
```javascript
const xhrOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
const xhr = this;
if (arguments == url) {
const getter = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'response').get;
Object.defineProperty(xhr, 'response', {
get: () => {
let result = getter.call(xhr);
//这里可以修改result
return result;
}
});
}
return xhrOpen.apply(xhr, arguments);
};
```
# 结语
撒花
cxxjackie大佬快给你剖完了 王一之 发表于 2021-11-1 11:05
cxxjackie大佬快给你剖完了
cxxjackie大佬天天被我骗代码{:4_110:} 加油加油,努力学习 cxxjackie小弟快给你剖完了 此代码多一字显肥,少一字显瘦,妍姿妖艳,心旌神摇 cxxjackie 发表于 2021-11-1 11:37
cxxjackie小弟快给你剖完了
快!掏代码!我要剖!呜呜呜呜 脚本体验师001 发表于 2021-11-1 13:21
此代码多一字显肥,少一字显瘦,妍姿妖艳,心旌神摇
安排! 控制台怎么输出xhr 的哥哥
劫持 感觉 好卡呀