v2主要依據是核心 JS 文件mkd_v2.js 版本,如下圖所示:
第一次?https://passport.baidu.com/cap/init?接口,請求的?ak
?是固定值,當然不同場景不同網站是不一樣的,_
?時間戳,ver=1,返回值?as
、tk
?都是后面會用到的。
請求https://passport.baidu.com/cap/style接口,會用到tk值,得到驗證碼圖片,如下圖:
請求https://passport.baidu.com/cap/log接口,會用到fs值,得到驗證結果,如下圖:
fs值計算方式:
v2 版本分析
v2 版本和 v1 版本基本上差不多,區別在于?rzData
?的結構不太一樣,ac_c
?的計算方法不一樣,以及 AES 的 IV 不一樣,先看 AES 的 IV,v2 版本是 as 值加上固定值?appsapi2
:
然后再看看?rzData
,common
?字段下基本上就是 v1 的?rzData
?的格式,captchalist
?下,至少有?spin-0
(旋轉)、`puzzle-0
(滑塊)、click-0
(點選)三種,ac_c
?依舊是旋轉角度占比、滑動占比以及點選坐標信息,其他的依舊是寫死或者置空就行。
然后就是?ac_c
?的計算方法了,首先是旋轉驗證碼,直接搜索?ac_c
:
往上跟棧,有個 percent 的地方,一個三目表達式,e 是固定值 290,e - 52 = 238
,238 也就是滑動條能夠滑動的最大長度:
如果我們識別出來的是旋轉角度?angle
,則?ac_c
?計算方法如下:
var distance = angle * 238 / 360
var ac_c = Number((distance / (290 - 52)).toFixed(2))
?
// 也可以直接寫成:
var ac_c = Number((angle / 360).toFixed(2))
而對于滑塊驗證碼就有所不同,同樣是這個地方的三目表達式,但是要走后面的邏輯:
如果我們識別出來的是滑動距離?distance
,則滑塊?ac_c
?的計算方法如下:
var ac_c = Number((distance / 290).toFixed(2))
同樣對于點選驗證碼來說,也不一樣,ac_c
?的值是點擊的 xy 坐標以及時間戳:
其他問題
前面我們說了百度的驗證應該有兩次,對于第二次驗證,也就是 v1 的?viewlog/c
?接口,v2 的?cap/c
?接口,即便你第一次校驗通過了,這個 c 接口校驗也有可能不通過,出現這種情況的原因是通過的時間太短了,隨機?time.sleep
?1-3 秒即可,如果時間太短,c 接口可能會報以下驗證錯誤:
{'code': 1, 'isRectified': False, 'msg': 'Verification Failed'}
還有一種情況就是提示存在安全風險,請再次驗證
,出現這種情況你會發現去瀏覽器手動滑也是一樣的,所以在本地加個再次驗證的邏輯就行了,一般來說第二次驗證就能通過。
{'code': 0, 'msg': 'success', 'data': {'f': {'feedback': 'https://www.baidu.com/passport/ufosubmit.html', 'reason': '存在安全風險,請再次驗證'}}}
然后就是請求 header 里沒有?Referer
?或者?Referer
?不正確的話,會報錯:
// v1 沒有 Referer
{'code': 1, 'msg': 'Unregistered Host'}
// v1 Referer 不正確
{'code': 1, 'msg': 'Invalid Request', 'data': []}
// v2 沒有 Referer 或者 Referer 不正確
{'code': 100600, 'msg': 'Unauthorized Host'}