前情介紹:
接口的安全性一向都是開發(fā)過程中比較在意的一件事情。如何測試已經(jīng)加密后的接口是現(xiàn)在測試開發(fā)人員常面對的一個問題。
預習知識:接口加密的測試
- 練習環(huán)境配置
- 實例1(UI自動化-百度搜索)
- 實例2(有效登錄)
- 實例3(無效登錄)
- 實例4 ( Appium )
- 實例5 ( 連接mysql數(shù)據(jù)庫)
- 實例6 ( GET/POST請求)
- 實例7(接口API測試)
- 實例8 (數(shù)據(jù)驅(qū)動)
- 實例9 (行為驅(qū)動)
- Appium Error總結(jié)
- robotframework Error總結(jié)
測試需求:
測試系統(tǒng)中添加公告的接口,此接口采用了 簽名加密的方式(API_KEY+Time)
測試設計:
測試 加密后的接口的方法其實和一般的接口測試是一致的。只是多了一步對傳輸?shù)臄?shù)據(jù)進行加密的過程。
用擴展庫的方式來完成數(shù)據(jù)的加密。(擴展庫的方式詳情-TBD,簡單的來說就是你可以自己寫Python文件,然后RF可以直接調(diào)用你所寫的Python文件)
Python中有很多庫都可以完成md5加密的功能,此次選取的是hashlib庫(提前自行安裝:pip install hashlib)
上圖中就是對sign_str進行一個md5加密的形式,md5加密是不可逆的,也就是說當你得到6648e929329e53e7a91c50ae685a88b5那一串東西的時候,你并不知道反編譯回來可以是@signpassword, BUT,你可以猜測啊,如果你猜它的md5原值就是@signpassword,最后你拿到加密后的值為6648e929329e53e7a91c50ae685a88b5,Bingo,恭喜你猜對了。所以呢,md5嚴格意義上來說是一種對稱加密的算法,不算特別安全,不過這里為了讓大家初步了解接口加密測試的方式,我們就從這里開始學習啦~~~
測試實現(xiàn):
1 編寫一個md5Enc.py文件,里面包含兩個函數(shù)
- get_sign 用來處理接口的簽名加密
- get_time_Stamp 用來處理把字符串模式的時間轉(zhuǎn)換為時間戳(這里是一個坑,因為RF中的get time本身得出來的時間是類似2017-07-24 11:47:20 格式的,而 此接口需要的time是時間戳格式)
2 RF中新建一個項目,在TestSuite層級上導入上面的md5Enc.py文件作為擴展庫(記得.py的后綴名需要加上的)
2 編寫一個返回值為200的正向接口測試的Testcase
第一行:獲取當前時間,賦值給變量t_now。
第二行:調(diào)用擴展庫中的get_time_Stamp函數(shù),將字符串格式的時間轉(zhuǎn)換成時間戳,賦值給變量t_now_stamp
第三行:打印出來看看值是否正常,主要用于調(diào)試
第四行:調(diào)用擴展庫中的get_sign函數(shù),將API_KEY+time的值進行md5加密
第五行:對報頭content-Type賦值后構(gòu)建為一個字典賦值給變量headers
第六行:將一個常量的時間賦值給變量start_time_str
第七行:將POST需要傳輸?shù)臄?shù)據(jù)構(gòu)造成字典對象賦值給變量payload
第八行:將payload中的sign取出來查看(為了調(diào)試,不必要)
第九行:建立一個Session開始準備發(fā)送請求
第十行:發(fā)送Post請求,所帶參數(shù)為之前所構(gòu)造好的參數(shù)
第十一行:對請求返回的status code進行斷言,正常應為200
第十二行:打印返回的值的json格式的內(nèi)容
第十三行:將返回的json格式值賦值給dict
第十四行到第十九行:對返回的值依據(jù)之前的接口定義文檔來進行斷言
附代碼(Robot TestCase)
*** Settings ***
Documentation A robot file to test the CryptAPI
Library RequestsLibrary
Library Collections
Library OperatingSystem
Library md5Enc.py
Library Signtest.py
*** Test Cases ***
AddEvent_Sign
${t_now} get time NOW #獲取當前時間
${t_now_stamp} get_time_Stamp ${t_now}
log ${t_now_stamp}
${sign_md5} get_sign ${t_now_stamp} #調(diào)用函數(shù)
${headers} Create Dictionary Content-Type=application/x-www-form-urlencoded
${start_time_str} set variable 2017-07-20 12:00:00
${payload} Create Dictionary eid=13 name=iphone8releasemeeting limit=2000 address=NewYork start_time=${start_time_str}
... time=${t_now_stamp} sign=${sign_md5}
${sign_log} Get From Dictionary ${payload} sign
Create Session event http://127.0.0.1:8000/api
${r}= Post Request event /sec_add_event/ data=${payload} headers=${headers}
Should Be Equal As Strings ${r.status_code} 200
log ${r.json()}
${dict} Set variable ${r.json()}
#斷言結(jié)果
${msg} Get From Dictionary ${dict} message
Should Be Equal ${msg} add event success
${sta} Get From Dictionary ${dict} status
${status} Evaluate int(200)
Should Be Equal ${sta} ${status}
Test
${message} add_event_success
Log ${message}
md5Enc.py(導入的文件需要和robot的項目在同一個文件夾內(nèi))
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import hashlib
import json
import time
class md5Enc(object):
def get_sign(self,t):
'''
Examples:
${sign_md5} | Get Sign |${t_now}
'''
keyMd5 = hashlib.md5()
api_key = "&Guest-Bugmaster"
sign_str = t + api_key
sign_bytes_utf8 = sign_str.encode(encoding="utf-8")
keyMd5.update(sign_bytes_utf8)
keyMd5 = keyMd5.hexdigest()
return keyMd5
def get_time_Stamp(self,t=''):
timeArray = time.strptime(t, "%Y-%m-%d %H:%M:%S")
timeStamp = int(time.mktime(timeArray))
timeStamp_str = str(timeStamp)
return timeStamp_str
#a=md5Enc.get_sign('sdf','2017-07-20 16:04:30')
CC先生說,擴展庫可以說是RF中非常強大的一個功能,如果想對之前的自動化測試代碼進行重構(gòu),又不想花費太多工夫的情況下,使用RF的擴展庫是再方便不過的功能。不過這里有一個坑是,如果你的Class里面的函數(shù)是以test開頭的可能添加會失敗。(不要問我是怎么知道的。。。一個多小時的時間就耗費在這個上面了。。。。)
圖片發(fā)自簡書App