q某音乐API接口分析--获取vKey和Sign
在q某音乐网站中,想要获得一首歌曲的资源链接(必须要这两个参数vKey和Sign有一定的难度)
步骤一:
F12打开开发者工具,在network中点击XHR,筛选ajxa请求(一般的数据请求都是使用ajax),这里这种数据都很简单,没有加密,没有sign(签名,口令等),不做分析
步骤二:
随便点击一个歌单,进入到歌单播放页面(https://y.qq.com/portal/player.html),右边红色圈圈里面的是歌曲的链接地址,一个一个试得出可以使用的地址在req_0.data.midurlinfo[0].purl
步骤三:
多次分析参数,发现该请求只有两个参数在变 sign 和 songmid,- 这个参数是个随机值,不变也可以。(逻辑关系,我们需要这两个参数才能得到vKey,歌曲资源链接是vKey和sign和歌曲songmid拼接组成,其它参数不变,如uin和guid)
步骤四:
我们再往前找,此时发现前面没有一个请求返回的数据跟sign的值一样,就说明sign不是由后端返回过来的,而是由前端js生成的。
这时我们ctrl+f进行关键词查找,搜索sign(关键词的选定需要根据经验来)
这里多次出现sign,说明有很大的可能性是我们要找的sign生成算法,然后打下断点看下结果。
这时我们在控制台输出这个函数,看一下返回的内容。发现正是我们需要的sign。
这时我们只需要把这个函数对应的代码复制下来,准备还原,控制台输出这个函数的代码:
多次断点发现,r(f, e, c, l, t)也是返回这个值。
通过对比,发现 sign 的位数不一样,且生成的签名串不一样,这时,我们进入到加密函数(getSecuritySign())内部,一步一步debug。
最后发现,它其实是动态的生成加密函数名,以及一个固定的加密串和随机函数。通过一个栈结构存储这些数据,并进行调用。
最终还原的代码如下所示:
这段代码由原网站复制得来,未改动
动态生成的执行代码:
function getSign(data) {
let str = 'abcdefghijklmnopqrstuvwxyz0123456789';
let count = Math.floor(Math.random() * 7 + 10);
let sign = 'zza';
for(let i = 0; i < count ; i++){
sign += str[Math.floor(Math.random() * 36)];
}
sign += global.__sign_hash_20200305('CJBPACrRuNy7'+JSON.stringify(data));
return sign
}
执行结果如下:
与之前的结果进行比较发现后32位是一样的,证明我们的算法是没有问题的
然后再根据sign获得vKey,在purl前面加上域名就能播放歌曲: