拿什么守護你,我的接口? 引自 http://www.jianshu.com/p/add7518a3fbe
接口測試那什么來做,這是剛接觸接口測試的同學最常問的問題。
個人覺得這個和你在拍照的時候是直接用美圖秀秀里面的濾鏡模式和自己去學PS后期進行處理圖片的邏輯是一樣一樣的。
在一般的情況下,濾鏡處理出來的和PS出來的效果一樣么?一樣
但是在妹子需要在背景里面加個城堡,鮮花滿地的時候,或者妹子需要做成女神一樣的特效的時候
濾鏡能處理么?不能。
PS能處理么?能!!!就是,就是,就是,學習成本稍微高一丟丟。
高的這一丟丟是什么呢?那就是我們經常在接口測試中遇到的各種各樣用來守護接口的安全機制問題。
以下圖片自行體會一下 接口測試工具和自行編寫接口測試代碼的區別。
美圖秀秀的效果圖:

PS處理的效果圖:

為啥非要費勁的在接口上加上各種復雜的安全機制呢?
好問題。
如果你不想自己的信息輕易的被泄露出去,自家網站被攻擊的癱瘓,公司倒閉,CEO跑路,男女朋友分手。。。還是乖乖的跟着CC先生看一下接口相關的安全機制吧。
一般接口開發中有以下常用的幾種安全機制:
- 用戶認證
- 數字簽名
- 接口加密
用戶認證
一般的接口測試工具都會提供一個User Auth/Authorization的選項,以Postman為栗子,你可以看到以下的選項:
- 基本認證(Basic Auth)
- 摘要認證(Digest Auth)
- OAuth 1.0a
- OAuth 2.0(最常見,現在的網站接口多數提供此用戶認證方式)
在對應的工具上,你可以選取對應的用戶認證選項,這里CC先生主要介紹如果用Python如何實現用戶認證。1 首先安裝Requests庫,Requests庫的get()和post()方法均提供有auth參數,用於設置用戶簽名。
2 假定我們有一個接口為添加一個新的公告,接口需要認證:auth=("username","password")
nid 或 name兩個參數二選一
3 偽代碼:def test_get_notice_list_nid_sucess(self): auth_user = ('admin' , 'admin123456') r = requests.get(self.base_url, auth = auth_user, params = {'nid' : 1}) result = r.json() self.assertEqual(result['status'], 200) ....
數字簽名
在使用 HTTP/SOAP 協議傳輸數據的時候,簽名作為其中一個參數,可以起到關鍵作用:
先來一個簡單的,通過客戶的密鑰,服務端的密鑰匹配;
這個很有好理解,例如一個接口傳參為:
http://127.0.0.1:8000/api/?a=1&b=2
假設簽名的密鑰為:@signpassword
加上簽名之后的接口參數為:
http://127.0.0.1:8000/sign/?a=1&b=2&sign=@signpassword
但是,這樣的sign 參數明文傳輸是不安全的,一般會選擇一些加密算法,比如MD5 算法(MD5算法是不可逆向的),比如MD5代碼如下:
import hashlib
md5 = hashlib.md5()
sign_str = "@signpassword"
sign_bytes_utf8 = sign_str.encode()
md5.update(sign_bytes_utf8)
sign_md5 = md5.hexdigest()
print(sign_md5)
執行后得到:6648e929329e53e7a91c50ae685a88b5
此時帶簽名的接口為:
http://127.0.0.1:8000/sign/?a=1&b=2&sign=6648e929329e53e7a91c50ae685a88b5
所以,當服務器接收到請求后,同樣需要對“signpassword”進行 MD5 加密,然后,比對與調用者傳來的 sign 加密串是否一致,從而來鑒別調用者是否有權限使用該接口。
接着,我們來理解一個復雜一點的:把sign參數傳遞為api key(申請獲取)+timestramp(時間戳)同樣需要 用代碼來實現,原理和上面這個一致的。(偽代碼)
def setUp(self):
self.base_url = "http://127.0.0.1:8000/api/sec_add_notice/"
# app_key
self.api_key = "&APIkey"
# 當前時間
now_time = time()
self.client_time = str(now_time).split('.')[0]
# sign
md5 = hashlib.md5()
sign_str = self.client_time + self.api_key
sign_bytes_utf8 = sign_str.encode(encoding="utf-8")
md5.update(sign_bytes_utf8)
self.sign_md5 = md5.hexdigest()
接口加密
通常接口會使用更復雜一點的方式來進行加密的操作,常見的是AES的使用,放一張圖讓大家感受一下AES加解密的過程:

詳細的過程可以參見http://www.mamicode.com/info-detail-514466.html 或者自行百度。
Python里面有一個很好的黑魔法,叫PyCrypto庫,支持常見的 DES、AES 加密以及 MD5、SHA 各種 HASH 運算。(官方網站下載最新版本:https://www.dlitz.net/software/pycrypto/
另外,也可以在 PyPi 倉庫中下載安裝:https://pypi.python.org/pypi/pycrypto)
對於AES的加密來說,看一下用了PyCrypto庫的結果
加密:
from Crypto.Cipher import AES
# 加密
obj = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
message = "The answer is no"
ciphertext = obj.encrypt(message)
print(ciphertext)
程序運行后的結果為:b'\xd6\x83\x8dd!VT\x92\xaa`A\x05\xe0\x9b\x8b\xf1'
AES加密里面有兩個關鍵,一個是key(必須為16,24,32位),一個是VI(必須為16位)
解密:解謎者必須要同時知道key和VI才可以解密
obj2 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
s = obj2.decrypt(ciphertext)
print(s)
===
So,接口加密測試的關鍵就在於開發小哥哥們用了什么加密算法來加密接口。你用相同的加密算法來加密你要發送的值 即可。
CC先生說,現在有很多的公司也把加密的算法直接封裝成一個類或者一個接口,也就是測試的時候,你直接調用加密的類或者加密的接口即可完成你的加密工作。剩下的接口測試和以往沒加密的接口測試一樣沒兩樣了。
附送一個Pypi庫里一堆加密算法庫的鏈接,自取:
https://pypi.python.org/pypi?%3Aaction=search&term=crypt&submit=search
作者:CC先生之簡書
鏈接:http://www.jianshu.com/p/add7518a3fbe
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。