分析网易云评论接口过程

1. 打开任意一首歌曲页面,很明显看到歌曲id=553310243

歌曲ID

2. Network查看异步请求XHR,找到评论接口

评论接口

由于网易云使用了了iframe,如果network勾选了GroupByFrame选项,则注意接口可能在iframe下。

3. 分析一下接口参数

接口参数

可以看到参数如下:

Query String Param:
csrf_token=

Form Data:
params=tCXVWGXv7AbTPYxwM5Nx9kkPXT0C4NufRsLk7yWolAcvJEi3fNk1b2jM%2Bi0jq6vckt7Fi7hkhyWkTVHmfBQGCVhfPlFwKSjPOf7DHJJ5S01NvEA637ddn6CTuUuHYxvQ0029Ju8ddYUvO9NfMpa%2BV%2BxYHDUq1ECHTuIJwIZov7rilCdP4sFgIBLQarbWFPwZ
&
encSecKey=7ec9d5faf5a1143895d392cb921abcfd8fc5e4b31a9dc8b031550ec8955eddba4cc20e952f6c4c1db846bb996c5961bbb1dfb3f1049fd6a797d2802580433fa01c159d3fa630ad2d8461ddabfbc4c534bb001cf4ba9ce8a617e181d07d7fe861bbe462e516fd7b7b56e09bc0293fed9f19679a86d911d12ac6997966f0f23fde

csrf_token为空即可,主要是分析两个表单参数paramsencSecKey从何而来。

4. 分析

找到请求发起处

ctrl+左键进入js,点击美化js方便阅读。

找到请求发送的code

分析一下前后代码,都是闭包,在方法头下断,看一下有没有需要的参数。

断点

看到闭包返回的函数的形参就包含了需要的参数。那么接下来分析哪里调用了闭包返回的函数。

闭包函数调用处

接下来分析d0x这个参数从何而来。

下断

看到需要的参数是形参获得,继续查看调用栈谁传的参数。

继续查看调用者

参数又是形参获得,继续向上分析调用栈。

关键代码
var bBB5G = window.asrsea(JSON.stringify(j0x), bor2x(["流泪", "强"]), bor2x(Ow3x.md), bor2x(["爱心", "女孩", "惊恐", "大笑"]));
e0x.data = k0x.cD1x({
  params: bBB5G.encText,
  encSecKey: bBB5G.encSecKey
})

四个参数。

参数:JSON.stringify(j0x)
"{"rid":"R_SO_4_551816010","offset":"0","total":"true","limit":"20","csrf_token":""}"
参数:bor2x(["流泪", "强"])
"010001"
参数:bor2x(Ow3x.md)
"00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
参数:bor2x(["爱心", "女孩", "惊恐", "大笑"])
"0CoJUm6Qyw8W8jud"

四个参数值如上所示,凭借经验(第一个参数中,csrf_token一直为空,rid为R_SO_4_歌曲id,其余字段固定即可;Ow3x.md是一个数组,内容类似emoji;其余参数是常量;当然不绝对是这样,也许js是后台动态生成填充了常量)分析后3个参数为固定参数。

bBB5G对象中包含了encTextencSecKey。接下来分析window.asrsea(a0,a1,a2,a3)如何生成的bBB5G对象。

有开发经验的大概能猜到这个window.asrsea函数是对参数进行加密操作,每次请求前加密参数,因此每次ajax请求都会调用这个加密方法,也就是说如果能逆向出加密方法,即可抓取该网页所有请求数据。

函数内部
a函数

可以确定,a(16)代表产生一个16位的随机数(其实看a()函数逻辑也可以发现就是产生随机长度的字母数字组合字符串)

ia生成,则i可以为固定值,将其固定为0000000000000000

encSecKeyi/e/f加密获得,因此可以得到(由于i被固定为0000000000000000)固定值babc57ca9e9ffb0a879ae290ac6cba6f60620aa9ae3b36a84585e23bbc73d73b13a2ebab4aa2ee80544d255727adc5a04db613d77d02a62a52b3a03134d16f191d54675f560f797c7f03e3a30c43df8b1b49878fd225b62f5f78041427debc3e95b93582f130618630702621da4eda9c71af91836cc39ab3b760b033643a1889

e0x.data = k0x.cD1x({
  params: bBB5G.encText,
  encSecKey: bBB5G.encSecKey
})

此时,已经得到了encSecKey,再看看params是怎么得到的。

params
两次加密

b函数内部很直观,使用了谷歌的CryptoJS库,使用方法可以参考CryptoJS 加密的使用方法。

b函数先对"{"rid":"R_SO_4_551816010","offset":"0","total":"true","limit":"20","csrf_token":""}"与固定参数"0CoJUm6Qyw8W8jud"进行一次AES对称加密;再对第一次的加密结果与i0000000000000000进行一次AES对称加密,返回结果encText

使用在线加密网站验证一下思路
使用在线加密网站验证一下思路

事实证明思路没错。

5. 总结:

请求的URL:http://music.163.com/weapi/v1/resource/comments/R_SO_4_551816010?csrf_token=
表单参数:

// 加密伪函数
function aesEnc(rawData,key,iv){
  var key = CryptoJS.enc.Utf8.parse(key)
        , iv = CryptoJS.enc.Utf8.parse(iv)
        , rawData = CryptoJS.enc.Utf8.parse(rawData)
        , encData = CryptoJS.AES.encrypt(rawData, key , {
          iv: iv,
          mode: CryptoJS.mode.CBC
      });
      return encData .toString()
}

params: aesEnc(aesEnc('{"rid":"R_SO_4_歌曲ID","offset":"0","total":"true","limit":"20","csrf_token":""}','0CoJUm6Qyw8W8jud','0102030405060708'),'0000000000000000','0102030405060708')
encSecKey: babc57ca9e9ffb0a879ae290ac6cba6f60620aa9ae3b36a84585e23bbc73d73b13a2ebab4aa2ee80544d255727adc5a04db613d77d02a62a52b3a03134d16f191d54675f560f797c7f03e3a30c43df8b1b49878fd225b62f5f78041427debc3e95b93582f130618630702621da4eda9c71af91836cc39ab3b760b033643a1889

你可能感兴趣的:(分析网易云评论接口过程)