利用python爬取yapi後臺介面
解決的問題:檢測公司釋出系統之中,遺漏的介面路徑地址。
採取的方法:爬取yapi管理後臺,爬取所有的介面路徑,同時檢測這個path路徑是否在釋出系統之中(如果不在釋出系統之後,通過域名訪問,會提示沒有許可權)
好了瞭解了背景之後 我就開始開工了。
一、瞭解yapi
在這裡小編看到了 左邊是產品 右邊是產品對應的模組名稱 點選模組名稱 我們可以看到很多個介面地址。
二、分析問題
瞭解到yapi的大致情況之後,我們知道點選產品,之後點選產品所屬的模組,每個模組下面有對應模組的介面地址,相比就知道了,就二個迴圈解決的問題
1.根據產品id(這裡我叫做group_id ) 找尋所有的模組id ,分析如下
2.根據模組id,找尋所有的介面路徑。
3.找到一個介面路徑 就通過requests請求對應地址訪問一下,如果許可權不足的就儲存下來。
初略的瞭解了一下之後,我們發現獲取模組id,和獲取介面路徑哪裡,可能會分頁,為了避免進行翻頁爬蟲,簡化指令碼 小編這裡先將分頁條數(limit)擴大了,另外還有一個地方,就是檢查許可權不足的時候,返回的格式是byte的我們需要decode轉成str字串的格式,但是呢,有些介面返回的又不是byte,所以當你把所有的介面都強制decode的時候,可能會報異常,這裡我通過使用"pass"得到了解決。
當然這裡換種策略 不選擇爬yapi後臺的話,也可以連線資料庫進行查詢在校驗的(mongodb)
三、程式碼部分
# author: xiejiangpeng # time:2018/11/7/20:35 # python:python3.6 # message: 連線api.host.com獲取介面 校驗許可權 import requests import json import time class CheckUrlJurisdiction(object): """ 例項初始化欄位說明 userapi: api後臺登入賬號 useradmin: base後臺登入賬號 passwdapi: api後臺登入密碼 passwdadmin: base後臺登入密碼 group_id: api後臺需要檢測產品id(base:35 團購:176) self.countTotal: path總數 self.countnum: path許可權不足數量 self.pathmodle: path所屬模組名稱 self.pathname: path詳細名稱 self.time: 執行花費時間 """ def __init__(self, userapi, useradmin, passwdapi, passwdadmin, group_id): self.userapi = userapi self.useradmin = useradmin self.passwdapi = passwdapi self.passwdadmin = passwdadmin self.group_id = group_id self.countTotal = 0 self.countnum = 0 self.pathmodle = "" self.pathname = "" self.time = float() self.apiurl = "http://api.host.com" self.adminurl = "http://base.host.com" self.api = requests.session() self.admin = requests.session() """api_login""" loginjson = {'email': self.userapi, 'password': self.passwdapi} loginheader = {'Content-Type': 'application/json;charset=UTF-8'} print("api後臺登入狀態:", self.api.post(url=self.apiurl + "/api/user/login", data=json.dumps(loginjson), verify=False, headers=loginheader).json().get("errmsg")) """admin_login""" loginbody = {'name': useradmin, 'password': passwdadmin, 'verify_code': ''} print("base後臺登入狀態: %s" % self.admin.post(url=self.adminurl + "/superAdmin/loginSuper/login", data=loginbody, verify=False).json().get("status")) def geturlpath(self): """根據group_id獲取對應模組id limit為每頁模組條數""" print("正在檢測釋出系統遺漏的介面地址(本次程式檢測所花費時間可能較長,請耐心等待)") starttime = time.clock() getid = {'group_id': self.group_id, 'page': '1', 'limit': '50'} ids = self.api.get(url=self.apiurl + "/api/project/list", verify=False, params=getid).json().get("data").get( "list") for i in range(0, len(ids)): self.pathmodle = ids[i].get("name") self.get_path_by_id(ids[i].get("_id")) timeend = time.clock() self.time = str("%.2f" % (timeend - starttime)) """通過模組id找尋path""" def get_path_by_id(self, _id): """避免翻頁,條數設定為999""" details = self.api.get(self.apiurl + "/api/interface/list?page=1&limit=999&project_id=%s" % _id, verify=False).json() for j in range(0, len(details.get("data").get("list"))): self.countTotal += 1 path = details.get("data").get("list")[j].get("path") self.pathname = details.get("data").get("list")[j].get("title") self.check_path(path) """根據path提取出沒有許可權的資訊""" def check_path(self, path): """檢查是否有許可權""" result = self.admin.get(url=self.adminurl + path, verify=False) if result.status_code == 200: try: if result.content.decode("utf-8").find("許可權") != -1: print("%s url資訊:%s/%s" % (path, self.pathmodle, self.pathname)) self.countnum += 1 except UnicodeDecodeError: pass if __name__ == "__main__": xiejiangpeng = CheckUrlJurisdiction("apiuser", "baseuser", "apipasswd", "basepasswd", "group_id") xiejiangpeng.geturlpath() print("總共檢測path數 %s" % xiejiangpeng.countTotal) print("許可權不足path數 %s" % xiejiangpeng.countnum) print("本次檢測所需時間為 %s秒" % xiejiangpeng.time)
四、執行效果
八百五十七個介面檢測完畢 總共花費時間三分鐘不到 找出許可權不足的數量為15個
好了分享到此結束,指令碼需要優化的地方還有很多,比如:執行完畢之後通過郵件的形式傳送給對應的人員,並且還可以優化一下產品id,以及模組下面對應的url採取分頁爬蟲的形式等等等。以後給大家分享其他的有關資訊