源代码出自 https://scriptcat.org/script-show-page/47/code
以下内容是对代码的一个解释
// ==UserScript==
// @name xhr
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match http://*/*
// @match https://www.baidu.com/
// @match https://so.csdn.net/*/*
// @grant none
// ==/UserScript==
(function () {
"use strict";
//劫持函数
function addXMLRequestCallback(callback) {
// oldSend 旧函数 i 循环
var oldSend, i;
//判断是否有callbacks变量
if (XMLHttpRequest.callbacks) {
//判断XMLHttpRequest对象下是否存在回调列表,存在就push一个回调的函数
XMLHttpRequest.callbacks.push(callback);
} else {
//如果不存在则在xmlhttprequest函数下创建一个回调列表/callback数组
XMLHttpRequest.callbacks = [callback];
// 保存 XMLHttpRequest 的send函数
oldSend = XMLHttpRequest.prototype.send;
//获取旧xml的send函数,并对其进行劫持(替换) function()则为替换的函数
//以下function函数是一个替换的例子
XMLHttpRequest.prototype.send = function () {
// 把callback列表上的所有函数取出来
for (i = 0; i < XMLHttpRequest.callbacks.length; i++) {
// 把this传入进去
XMLHttpRequest.callbacks[i](this);
}
//循环回调xml内的回调函数
// 调用旧的send函数 并传入this 和 参数
oldSend.apply(this, arguments);
//由于我们获取了send函数的引用,并且复写了send函数,这样我们在调用原send的函数的时候,需要对其传入引用,而arguments是传入的参数
};
}
}
// e.g.
//传入回调 接收xhr变量
addXMLRequestCallback(function (xhr) {
//调用劫持函数,填入一个function的回调函数
//回调函数监听了对xhr调用了监听load状态,并且在触发的时候再次调用一个function,进行一些数据的劫持以及修改
xhr.addEventListener("load", function () {
// 输入xhr所有相关信息
console.log(xhr);
if (xhr.readyState == 4 && xhr.status == 200) {
// 如果xhr请求成功 则返回请求路径
console.log("函数1", xhr.responseURL);
}
});
});
// Your code here...
})();
XHR劫持是以csdn搜索页面为例子
![](https://i-blog.csdnimg.cn/blog_migrate/4344c0835c28a0c44bf3b833fb8ad228.png)
上述代码开启插件后,运行之后页面还是正常状态,控制台会输出xhr请求的路径,如下:
![](https://i-blog.csdnimg.cn/blog_migrate/f322dae8eb2c68df86c8c89c10cce682.png)
接下来是劫持网页原本发出的请求,替换成自己的数据:
// ==UserScript==
// @name xhr拦截
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match http://*/*
// @match https://www.baidu.com/
// @match https://so.csdn.net/*/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
function addXMLRequestCallback(callback){
//debugger;
//是一个劫持的函数
// oldSend 旧函数 i 循环
var oldSend, i;
//判断是否有callbacks变量
if( XMLHttpRequest.callbacks ) {
//判断XMLHttpRequest对象下是否存在回调列表,存在就push一个回调的函数
XMLHttpRequest.callbacks.push( callback );
} else {
//如果没有则创建一个callback数组 //如果不存在则在xmlhttprequest函数下创建一个回调列表
XMLHttpRequest.callbacks = [callback];
// 保存 XMLHttpRequest 的send函数
oldSend = XMLHttpRequest.prototype.send;
//获取旧xml的send函数,并对其进行劫持(替换) function()则为替换的函数
XMLHttpRequest.prototype.send = function(){
// 这里进行一些对自己数据的操作
// 发送请求
fetch("https://api.apiopen.top/api/getImages?type=animal&page=1&size=10")
.then(response=> response.json())
.then(result =>{
//获取被替换的dom
const dom = document.getElementsByClassName("main-lt")[0];
dom.innerHTML = result.result.list[0].title
})
//循环回调xml内的回调函数
// 调用旧的send函数 并传入this 和 参数
oldSend.apply(this, arguments);
//oldSend.apply(1);
//由于我们获取了send函数的引用,并且复写了send函数,这样我们在调用原send的函数的时候,需要对其传入引用,而arguments是传入的参数
}
}
}
// e.g.
//传入回调 接收xhr变量
addXMLRequestCallback( function( xhr ) {
//调用劫持函数,填入一个function的回调函数
//回调函数监听了对xhr调用了监听load状态,并且在触发的时候再次调用一个function,进行一些数据的劫持以及修改
//对xhr进行事件监听 判断是load 再回调function函数
xhr.addEventListener("load", function(){
console.log(xhr)
if ( xhr.readyState == 4 && xhr.status == 200 ) {
// 输入当前的路径
console.log( '函数1',xhr.responseURL );
}
});
});
// Your code here...
})();
结果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/4d9b29ae10a04de4e6abf22afa252402.png)