题目地址:aHR0cHM6Ly9tYXRjaDIwMjMueXVhbnJlbnh1ZS5jbi90b3BpYy8x
一、页面调试
1)在控制台搜索接口名称可以很容易定位到发送请求的地方,代码可读性比较好,可以直接在相关函数内打上断点;
2)点击页码触发请求逻辑,在右侧面板可以看到相关的变量。
请求总共需要传3个参数“now、page、token”,其中,now(当前时间戳)和page(当前页码)比较简单,主要是提取token的生成方法;
从代码中可以知道 token 的计算公式为:MD5(AES(now + page)),意即:将时间戳和页码的字符串进行拼接,再对拼接后的字符串进行AES加密,接着对AES加密后的字符串内容进行MD5计算。
起初,我直接使用网上公共的AES加密方法来实现代码,但发现请求会报错“token无效”,这时才恍然网站的AES加密是不同的。
二、代码实现
代码的关键点主要是提取AES加密方法,这里有两个方案:
方案一
在正式发送请求之前,可以在断点调试过程中,将AES加密的方法右键存为全局变量,以便在后续的函数中使用。这种方式有点讨巧,不用去花太多时间在去提取代码。
// 变量声明:请求成功的次数
let count = 0;
// 变量声明:所有请求到的数据
let dataList = [];
// 函数声明:发送请求获取页面数据
let getPageData = function (pageNum) {
let timestamp = Date['now']()
, iv = '666yuanrenxue66'
, h = temp1['AES']['encrypt'](timestamp + String(pageNum), iv, {
'mode': temp1['mode']['ECB'],
'padding': temp1['pad']['Pkcs7']
})
, i = '/api/match2023/1'
, j = {
'page': String(pageNum),
'token': temp1['MD5'](h['toString']())['toString'](),
'now': timestamp
};
$['ajax']({
'url': i,
'dataType': 'json',
'async': !![],
'data': j,
'type': 'POST',
'beforeSend': function(k) {},
'success': function(k) {
k = (k['data'] || []).map(v => v.value);
dataList = [...dataList, ...k];
count++;
if (count >= 5) {
let sum = dataList.reduce((a, b) => (a + b), 0);
console.log('sum:', sum)
}
},
'complete': function() {},
'error': function() {
}
});
}
// 开始运行:循环依次发送各个页面的数据请求
for (let i = 1; i <= 5; i++) {
setTimeout(() => {
getPageData(i)
}, i * 200)
}
方案二
提取加密相关代码。好在代码都集中在 /corejs/match1.js 文件中。经过分析,其实修改的内容并不多,只需将第34~75行之间的Ajax请求做些许调整。
1)去除了初始化时对call函数的调用;
2)修改Ajax请求成功后的回调函数。
修改后的代码执行完成后,会在全局生成一个名为call的函数,这个函数就是用来请求页面数据的。
// 微调 corejs/match1.js 内容:重新定义全局call方法
// ...前方省略
0x2: [function(a, b, c) {
call = function(d, cb) {
// ...略
$['ajax']({
'url': i,
'dataType': 'json',
'async': !![],
'data': j,
'type': 'POST',
'beforeSend': function(k) {},
'success': function(k) {
k = k['data'];
cb && cb(k);
},
'complete': function() {},
'error': function() {
}
});
}
}
// ...后方省略
// 变量声明:请求成功的次数
let count = 0;
// 变量声明:所有请求到的数据
let dataList = [];
// 函数声明:请求成功后的回调函数
let callback = function (data) {
data = (data || []).map(v => v.value);
dataList = [...dataList, ...data];
count++;
if (count >= 5) {
let sum = dataList.reduce((a, b) => (a + b), 0);
console.log('sum:', sum)
}
}
// 开始运行:循环依次发送各个页面的数据请求
for (let i = 1; i <= 5; i++) {
setTimeout(() => {
call(i, callback)
}, i * 200)
}