網易雲音樂API獲取分析

喜歡的朋友star一下
終於對網易雲音樂下手了!
一、網易雲音樂歌曲評論數據獲取分析

本來是想着用jsoup來爬取網易的評論,結果一分析發現獲取的網頁中找不到評論數據。研究了半天,無果。於是百度看看。
果然是大廠,在安全方面肯定做的比較多,原因是在傳遞參數的時候對參數進行加密,所以在我們直接訪問網址的時候,如果傳遞的參數沒有經過加密,前端頁面就獲取不到數據。看看知乎的大神們的解法:https://www.zhihu.com/question/36081767
下面是我的分析:
 
我們先對頁面分析:
1、首先通過URL得知歌曲的固定id
2、這是我們需要查看的歌曲
3、通過開發者工具可以找到評論的API接口
4、我們可以看到response給我們的是json數據,我們所需要的評論數據就是包含在json數據中。
 
 
現在問題來了,API接口知道了,直接訪問行不行呢?答案是,肯定不行啊!最起碼我們要把歌曲的id傳過去,纔可以找到指定的評論啊。
通過分析可以知道,參數沒有放在URL中,所以參數肯定是post過去的。要不怎麼說是大廠呢,就算是你把參數放在請求頭也是不行的!如果我是產品經理肯定要程序員去加密傳輸數據,我大廠的數據豈是你能隨便獲取的!
繼續分析:

通過在header中我們可以發現完整的請求地址,以及包頭的一些參數配置。

重點來了:

data中我們發現了兩個參數,對,就是加密之後的參數,肯定看不懂啦。這都是加密之後的密文。這裏肯定是我們要傳遞的參數,包括歌曲的id什麼的,但是加密算法我們怎麼能知道呢?
走到這一步我們似乎前一腳已經踏進去了,還沒有落地,發現腳下埋着地雷!
不急不急,再神祕的算法也是人寫的嘛!總會有破解的方法。
 
 
二、post數據加密破解
爲了安全問題,一般程序員或多或少會對數據進行加密。一般加解密的程序只有開發者自己清楚。
總是有那麼些大牛平時沒事幹就喜歡琢磨這些事情,通過破解這些程序來證明自己。還有的是爲了喜歡的女孩,比如下面這位:(這是一個悲傷的故事!)

這位同學的代碼分析能力很強,他提供的方法屬於另闢蹊徑。其他的大牛都是通過分析js加密算法,然後自己寫出來,實現對傳輸參數的加密,大部分都是使用Python,這位作者使用的是純Java寫的加密程序。通過java內置的ScriptEngine調用js引擎,實現對js中的方法調用,這個我也是第一次聽說,在JavaSE6中提供的功能。什麼是ScriptEngine,請看博客:https://www.cnblogs.com/zouhao/p/3644788.html或者
作者通過對core.js的核心文件分析,將兩萬行的代碼刪減成一千多行,不得不說作者很有耐心啊!最後就簡單了,直接在java代碼中調用js的方法就可以對參數進行加密了。
 
現在對代碼進行分析:

1、首先分析JSSecret.java

一開始是static中實現起始加載的功能
1)首先使用Java的NIO實現對文件的讀取,Path和Files,對於以往的各種IO流大家是不是寫吐了
2)第二步使用ScriptEngineManager,詳情看下面的官方API,使用getEngineByName()方法指定參數,可以獲取指定腳本的ScriptEngine的對象。


3)第三步創建ScriptEngine對象

ScriptEngine是一個基礎接口,它的eval方法如下:

也就是說當我們將js代碼放入到eval中當做參數就可以執行相應的js代碼。
  1. Invocable
這一步我們就要調用js中的方法,上一步我們獲取到了js的對象,我們來看看什麼是Invocable

它是幹什麼的呢?它就是用來調用js中指定的方法的


2、js中實現參數加密:

Core.js中部分代碼:

讓我們來看看網易的js代碼


這些都是什麼鬼,你沒看錯,找不到變量名稱吧,一般寫程序都是按照功能給變量起特定的名字,但是網易的全是abcdefg什麼的,這裏應該是使用了代碼混淆!
1)第一步可以看到。此處執行了core.js中myFunc()方法,將傳入的參數paras進行加密。那麼paras參數是什麼呢?通過程序運行可以看出paras參數是一個json數據集,包含了四個參數,實際測試隨着接口的不同參數是可以改變的,csrf_token親測給不給數據沒關係的。主要是offset和limit,懂數據庫的同學應該懂得,起始位置和返回數據的數目。Uid可以根據具體的需求來改,參數名稱可以從URL中獲取到。
 
大家再看看ScriptObjectMirror這個東西,這又是什麼鬼?在java6API找了一圈,結果沒找到,java7才支持的,可見作者的見識很廣。但是奇怪的是從1.7找到1.8也找不到這個東西!
 
沒辦去去Oracle的官網去看API了,是不是這玩意太偏了,一般用不到。鏈接如下:
你沒看錯,這是JDK9,也就是Java9API,我能怎麼辦,我也很無奈啊!先看官方解釋:

大家看一看,這不就是和Map非常相似嘛,get(參數)方法中的參數就是key,返回值就是value,下面我們來驗證一下:這應該是set集合,以Map.Entry<String,Object>爲泛型類型,通過foreach我們就可以獲取so存儲的全部的值。它的兩個key分別是encTextencSeckey,它們的值就是js加密過後的值。
 
 
 
下面是它的源碼:
publicObject get(finalObject key) {
    checkKey(key);
    return this.inGlobal(newCallable() {
       publicObject call() {
           returnScriptObjectMirror.translateUndefined(ScriptObjectMirror.this.wrapLikeMe(ScriptObjectMirror.this.sobj.get(key)));
       }
    });
}
 
2)第二步就是在Map中設置這兩個值,最後整個方法返回一個map對象。
 
三、數據請求測試
分析測試類:
 
1)將請求參數封裝到json中。

2)封裝請求頭。
3)請求頭中主要修改的是url和data的參數,也就是請求地址和攜帶的參數。
4)最後通過API接口返回完整的json數據

 
 

四、爆出其它的API接口:

通過分析各種頁面,發現參數加密方式都是一致的,所以這就很簡單了,其它的接口也都出來了。下面做個總結:
1、搜索API
 
原來的網頁地址:
http://music.163.com/#/search/m/?id=28193075&s=%E5%9C%A8%E4%BA%BA%E9%97%B4&type=1
 
(%E5%9C%A8%E4%BA%BA%E9%97%B4)這個就是我們在搜索框中輸入內容
 
搜索建議:
http://music.163.com/weapi/search/suggest/web?csrf_token=
 
按類型搜索:
http://music.163.com/weapi/cloudsearch/get/web?csrf_token=
 
 
在原地址上面傳遞的參數可以分析:
type類型的不同,搜索的類型不同
type=1             單曲

type=10           專輯

type=100         歌手

type=1000      歌單

type=1002      用戶

type=1004       MV

type=1006      歌詞

type=1009      主播電臺
 
 
 
2、查看粉絲
請求頭:
Referer:http://music.163.com/user/fans?id=97526496
 
獲取指定用戶的粉絲:
http://music.163.com/weapi/user/getfolloweds?csrf_token=
 
 
3、動態:
http://music.163.com/user/event?id=97526496
http://music.163.com/weapi/event/get/97526496?csrf_token=
 
 
4、播放
http://music.163.com/weapi/song/enhance/player/url
直接播放地址:id可以改爲任何存在的歌曲的ID
 
5、評論(熱門評論和全部評論)
516392300這就是歌曲的id
http://music.163.com/weapi/v1/resource/comments/R_SO_4_516392300?csrf_token=1ac15bcb947b3900d9e8e6039d121a81




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章