雪球app抓包与mock实战

标题

雪球app抓包与mock实战

课程价值

  • 掌握 mock 使用场景,基本 mock 原理
  • 掌握抓包工具charles、mitmproxy的使用和应用场景

大纲

  • mock基本原理
  • charles map local实战回顾
  • mitmproxy 安装
  • mitmproxy 实战练习

时长

90 分钟

内容

mock原理与使用场景

官方文档

Introduction

原理

  • 使用场景

    • 前后端分离,被测对象是前端
    • 模拟第三方服务的响应数据,达到测试目的
    • 解耦硬件设备,模拟硬件的返回信息
  • 使用条件

    • 了解响应的数据格式
    • 服务与mock服务的通讯协议保持一致

charles_map_local回顾

mitmproxy原理

mitmproxy 安装

  • mac环境
brew install mitmproxy
  • windows 环境
  • 在 windows 中,以管理员身份运行 cmd 或 power shell
  • 命令:
pip install pipx
pipx install mitmproxy

或者直接使用 pip install mitmproxy

  • 安装之后需要配置环境变量:安装成功的提示中会给出需要配置的目录,将其配置到path环境变量中重启cmd即可

检查是否安装成功

mitmdump --version

证书配置

  • 在浏览器连接代理
  • 输入 mitmdump 开启mitmproxy 的服务
  • 进入mitm.it 页面
  • 选择对应的系统下载、安装

手机

  • 进入手机完成网络配置

  • 输入 mitmdump 开启mitmproxy 的服务

  • 进入mitm.it 页面

  • 选择对应的系统下载、安装

mitmproxy

  • windows 不支持只有mac支持
  • 命令行交互工具

mitmweb

  • 网页工具

mitmdump

  • 查看命令信息
mitmdump --help
  • 指定监听端口
mitmdump -p [监听端口]
  • 指定关联的python脚本
mitmdump -s [指定脚本1路径]

rewrite

"""Send a reply from the proxy without sending any data to the remote server."""
import json

from mitmproxy import http

from mitmproxy import ctx


class Counter:
    def __init__(self):
        self.num = 0

    def request(self, flow: http.HTTPFlow):
        self.num = self.num + 1
        ctx.log.info("We've seen %d flows" % self.num)
        # 判断是否是想要的请求信息,通过url进行判断

    def response(self, flow):
        if "https://stock.xueqiu.com/v5/stock/batch/quote.json?_t=" \
                in flow.request.pretty_url:
        # 修改原始数据
        # 获取的text 是str类型,如果要对数据进行操作,需要进行数据转换
            data = json.loads(flow.response.text)
            data["data"]["items"][0]["quote"]["name"] = "hogwarts"
            data["data"]["items"][1]["quote"]["name"] = "hogwarts"
            data["data"]["items"][2]["quote"]["name"] = "hogwarts"
            flow.response.text = json.dumps(data)
        # 赋值给响应信息


addons = [
    Counter()
]

map_local

"""Send a reply from the proxy without sending any data to the remote server."""
import json

from mitmproxy import http

from mitmproxy import ctx


class Counter:
    def __init__(self):
        self.num = 0

    def request(self, flow: http.HTTPFlow):
        self.num = self.num + 1
        ctx.log.info("We've seen %d flows" % self.num)
        # 判断是否是想要的请求信息,通过url进行判断

    def response(self, flow):
        if "https://stock.xueqiu.com/v5/stock/batch/quote.json?_t=" \
                in flow.request.pretty_url:
        # 打开文件,读取文件数据,作为响应,给返回
            with open("tmp2.json", encoding="utf-8") as f:
                data = json.load(f)
            flow.response.text = json.dumps(data)


addons = [
    Counter()
]

递归批量处理数据信息

"""Send a reply from the proxy without sending any data to the remote server."""
import json

from mitmproxy import http

from mitmproxy import ctx


class Counter:
    def __init__(self):
        self.num = 0

    def request(self, flow: http.HTTPFlow):
        self.num = self.num + 1
        # 判断是否是想要的请求信息,通过url进行判断

    def response(self, flow: http.HTTPFlow):
        if "https://stock.xueqiu.com/v5/stock/batch/quote.json?_t=" \
                in flow.request.pretty_url:
        # 打开文件,读取文件数据,作为响应,给返回
            data = json.loads(flow.response.text)
            flow.response.text = json.dumps(self.json_travel(data))


    def json_travel(self, data):
        # 判断传入的数据类型{"a": {"b":{"c":1}}}
        if isinstance(data, dict):
            # 遍历字典的数据
            # 当字典格式,递归value值
            for key, value in data.items():
                data[key] = self.json_travel(value)
        elif isinstance(data, list):
            # 当数据类型 为 list 的时候, 添加到结构内,并继续递归遍历,
            # 知道数据类型不为可迭代对象时
            data = [self.json_travel(value) for value in data]
        elif isinstance(data, bool):
            data = data
        elif isinstance(data, int) or isinstance(data, float):
            data = data * 2
        elif isinstance(data, str):
            data = data
        else:
            data = data
        return data

addons = [
    Counter()
]

脱离命令行执行方式

if __name__ == '__main__':

    sys.argv = [__file__, "-s", __file__]
    #
    # 官方要求必须主线程
    mitmdump()

课后反馈表

课后作业