mitmproxy修改接口返回
公司的软件库没有charles,也没有fiddler,也不让自己下载安装,只好自己写个代理修改接口返回了
在windows上安装和配置mitmproxy
-
安装mitmproxy包
pip install mitmproxy
-
在命令行打 mitmweb 看是否能起起来一个8081的web网页
能打开下图2的网页则说明安装成功了,但是如果还没安装过证书的话,是还看不到任何请求的。
-
安装证书
windows下,安装完mitmproxy后,系统会自动下载好了证书,路径在 C:\Users\你的用户名.mitmproxy
3.1 双击mitmproxy-ca.p12,进入证书导入向导
3.2 直接下一步后,不填密码,再直接下一步
3.3 选择证书存储选【受信任的证书颁发机构】
3.4 点击完成,证书就导入到当前用户\计算机的根证书存储里面了
chrome开代理
-
打开chrome的设置 -- 搜索“代理” -- 点击“打开您的计算机代理设置”, 此时会打开系统的代理设置窗口
-
在手动设置代理打开代理,设置好端口为8080, 保存。如果是要代理本地某些网段的端口,如172.18..,要注意地址是否写入了禁用列表,必须从列表移除掉才能抓到包。
-
此时再打开 mitmweb ,可以看到已经能抓到http包了
代码
- 获取请求头和request_body
如下实例会打印请求头,并把请求body写入文件里
# 来自client的 HTTP 请求被成功完整读取(包括请求头以及body)
def request(self, flow: mitmproxy.http.HTTPFlow):
filter_host = "172.18.34.102"
url_path = "http://172.18.34.102:9005/xxx-api/containerType/query"
if (str(flow.request.host) == filter_host) and (str(flow.request.url) == url_path):
self.num += 1
ctx.log(u"处理第 %d 个请求" % self.num)
ctx.log(flow.request.headers) # 打印请求头
with open(r'./request_body.txt', 'a', encoding="utf-8") as file:
# file.write(str(flow.request.headers))
file.write(str(flow.request.get_text())) # 保存请求body
print("request_body 写入成功")
生成了一个request_body.txt的文件
- 修改repsonse
# 来自server的 HTTP 响应被成功完整读取
def response(self, flow: mitmproxy.http.HTTPFlow):
filter_host = "172.18.34.102"
url_path = "http://172.18.34.102:9005/xxx-api/base/getEnum"
if (str(flow.request.host) == filter_host) and (str(flow.request.url) == url_path):
res = json.loads(flow.response.get_text())
res['data']['commonEnum']['containerKind'] = {'CARTON': "纸箱", 'PLASTIC': "塑料", 'AAA':'哈哈哈'} # 修改接口返回
flow.response.set_text(json.dumps(res))
ctx.log('modified limitCount: {}'.format(res))
- 完整代码
import mitmproxy.http
from mitmproxy import ctx
import json
from mitmproxy.tools.main import mitmweb
class proxy_example(object):
'''
利用mitmproxy模拟一获取\修改HTTP数据
'''
def __init__(self):
self.num = 0
# 来自client的 HTTP 请求被成功完整读取(包括请求头以及body)
def request(self, flow: mitmproxy.http.HTTPFlow):
filter_host = "172.18.34.102"
url_path = "http://172.18.34.102:9005/xxx-api/containerType/query"
if (str(flow.request.host) == filter_host) and (str(flow.request.url) == url_path):
self.num += 1
ctx.log(u"处理第 %d 个请求" % self.num)
ctx.log(flow.request.headers)
with open(r'./request_body.txt', 'a', encoding="utf-8") as file:
# file.write(str(flow.request.headers))
file.write(str(flow.request.get_text()))
print("request_body 写入成功")
# 来自server的 HTTP 响应被成功完整读取
def response(self, flow: mitmproxy.http.HTTPFlow):
filter_host = "172.18.34.102"
url_path = "http://172.18.34.102:9005/xxx-api/base/getEnum"
if (str(flow.request.host) == filter_host) and (str(flow.request.url) == url_path):
res = json.loads(flow.response.get_text())
res['data']['commonEnum']['containerKind'] = {'CARTON': "纸箱", 'PLASTIC': "塑料", 'AAA':'哈哈哈'}
flow.response.set_text(json.dumps(res))
ctx.log('modified limitCount: {}'.format(res))
# 处理响应异常, HTTP错误
def error(self, flow: mitmproxy.http.HTTPFlow):
pass
def websocket_message(self, flow: websocket.WebSocketMessage):
assert flow.websocket is not None # make type checker happy
# get the latest message
message = flow.websocket.messages[-1]
# was the message sent from the client or server?
if message.from_client:
logging.info(f"Client sent a message: {message.content!r}")
else:
logging.info(f"Server sent a message: {type(message.content)} {message.content!r}")
# manipulate the message content
# message.content = re.sub(rb"^Hello", b"HAPPY", message.content)
content = byte_to_dict(message.content)
event = content.get('event', None)
if event and event == 'station_info':
if content['data']['station'] ['code'] == '15':
content = readJson('station_info_15.json')
message.content = dic_to_byte(content)
addons = [
proxy_example()
]
if __name__ == '__main__':
mitmweb()
在控制台输入 mitmdump -p 8080 -s test_proxy.py