在編寫接口自動化測試用例或其他腳本的過程中,經常會遇到需要繞過用戶名/密碼或驗證碼登錄,去請求接口的情況,一是因為有時驗證碼會比較復雜,比如有些圖形驗證碼,難以通過接口的方式去處理;再者,每次請求接口前如果都需要先去登錄一次,這樣不僅效率低,還耗費資源。
有些網站是使用cookie辨別用戶身份的,此時我們便可以先登錄一次,拿到登錄成功后的cookie,后續請求時在請求頭中加入該cookie,便可保持登錄狀態直接請求。
cookie工作原理
HTTP協議1.0版本是無狀態的,對於事務處理沒有記憶能力,比如用戶登錄了某個網站后,再次刷新這個頁面去請求服務器,如果沒有相關機制的話,服務器是不知道這個請求是否還是刷新之前登錄的用戶發出來的。此時,為了維持用戶的登錄狀態,即為了使服務器能夠識別頁面刷新之后的請求,就可以使用cookie機制
。
cookie原理簡單概括如下:
-
用戶在客戶端 (一般為瀏覽器) 中訪問某個頁面 ,也就是向服務器發送請求。
-
服務器收到請求后,會在響應頭中設置
Set-Cookie
字段值,該字段存儲相關信息和狀態。 -
客戶端解析服務器HTTP響應頭中的Set-Cookie字段,並以key=value的形式保存在本地,之后客戶端每次發送HTTP請求時,都會在請求頭中增加Cookie字段。
-
服務器接收到客戶端的HTTP請求之后,會從請求頭中取出Cookie數據,來校驗客戶端狀態或身份信息。
以登錄某網站為例,點擊登錄時請求sign_in接口,請求成功后 (即登錄成功后) 在響應頭中會返回set-cookie字段,如下:
瀏覽器會保存上圖中set-cookie字段的值,后續發送請求 (即登錄后進行頁面操作) 時,請求頭中都會攜帶包含剛剛保存的set-cookie值的cookie,如下所示:
服務器接收到這個cookie后,便會用它去查找內存中的記錄,有則校驗成功。
由此可知,如果需要繞過用戶名密碼、驗證碼等進行模擬登錄,然后再去請求其他接口,那么我們可以先拿到登錄成功后的cookie,將cookie放在請求頭中,再去調用需要登錄才能請求的接口,便能調用成功。
cookie繞過登錄
1,哪些場景需要使用cookie繞過登錄?
-
網絡爬蟲,代碼去爬取某個網站時需要驗證碼登錄,而這時代碼獲取驗證碼登錄有一定難度,就可以先抓取到登錄后的cookie用於后續的接口請求。
-
接口自動化測試,對某個需要登錄的項目進行接口測試,每次請求時都先請求登錄接口進行登錄會影響效率而且極其不方便,這時就可以抓取到第一次登錄后的cookie,后續每次接口請求都帶上該cookie,服務器就會認為是登錄狀態。
-
其他需要繞過登錄的場景。
2,接下來舉例說明怎樣編寫python腳本,利用cookie機制繞過登錄。
-
需求:請求接口獲取博客園網自己賬號的個人信息。
-
需求分析:
- 需要先登錄博客園,才能去請求獲取個人信息接口拿到個人信息
- 該網站的登錄方式有兩種:用戶名、密碼登錄,手機驗證碼登錄
- 可嘗試使用cookie繞過這兩種登錄方式。
3,思路:
-
首先,先使用手機驗證碼登錄網站,Fiddler進行抓包,獲取登錄后的cookie信息;
-
然后,編寫python代碼,拿上一步中獲取到的cookie信息去請求獲取個人信息接口;
-
最后,個人信息獲取成功便說明繞過了登錄。
4,實際操作流程如下:
-
首先,登錄網站,Fiddler抓包獲取登錄成功后的cookie。
-
然后,cookie信息去請求獲取個人信息接口。
登錄后同樣可以抓取到獲取個人信息接口的信息,如下:
個人信息接口請求方式為GET,請求URL如圖所示,那么我們只需要這兩點信息就足夠了。接下使用上一步中拿到的cookie去請求這個接口。代碼如下:
import requests url = "https://account.cnblogs.com/user/userinfo" headers = { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.30", "cookie": "登錄成功后的cookie" } res = requests.get(url=url, headers=headers).text print(res)
運行代碼,結果如下:
可以看到,成功獲取了個人信息。
-
最后,為了驗證是cookie確實繞過了登錄,我們修改上面的腳本,不加入該cookie,請求個人信息接口,代碼如下:
import requests url = "https://account.cnblogs.com/user/userinfo" headers = { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.30" } res = requests.get(url=url, headers=headers).text print(res)
運行后結果如下:
從上圖可以看出來,不加登錄成功后的cookie去請求接口,則會提示先登錄或注冊。
總結
cookie繞過登錄其實是登錄狀態保持,而不是真的不需要登錄。
並非所有的網站都是使用cookie機制,除了cookie機制外,還有session、token等方式進行會話保持,這在后續的文章中會進行說明。