利用python爬取yapi后台接口

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Tester_xjp/article/details/83896013

解决的问题:检测公司发布系统之中,遗漏的接口路径地址。

采取的方法:爬取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采取分页爬虫的形式等等等。以后给大家分享其他的有关信息

猜你喜欢

转载自blog.csdn.net/Tester_xjp/article/details/83896013
今日推荐