稀土掘金 稀土掘金

Android抓包从未如此简单

一、情景再现:

有一天你正在王者团战里杀的热火朝天,忽然公司测试人员打你电话问为什么某个功能数据展示不出来了,昨天还好好的纳,是不是你又偷偷写bug了。。。WTF!,你会说:把你手机给我,我连上电脑看看打印的请求日志是不是接口有问题。然后吭哧吭哧搞半天看到接口数据返回的格式确实不对,然后去群里丢了几句服务端人员看一下这个接口,数据有问题。然后有回去打游戏,可惜游戏早已结束,以失败告终,自己还被无情的举报禁赛了。。。人生最痛苦的事莫过于此。假如你的项目已经集成了抓包助手,并且也给其他人员介绍过如何使用,那么像这类问题根本就不需要你再来处理了,遇到数据问题他们第一时间会自己看请求数据,而你就可以安心上王者了。

二、Android抓包现状

目前常见的抓包工具有Charles、Fiddler、Wireshark等,这些或多或少都需要一些配置,略显麻烦,只适合开发及测试人员玩,如果产品也想看数据怎么办纳,别急,本文的主角登场了,你可以在项目中集成 AndroidMonitor,只需两步简单配置即可实现抓包数据可视化功能,随时随地,人人都可以方便快捷的查看请求数据了。

三、效果展示

俗话说无图无真相

111.jpg

222.jpg

333.jpg

抓包pc.png

四、如何使用

抓包工具有两个依赖需要添加:monito和monitor-plugin

Demo下载体验

源码地址

1、monitor接入

添加依赖

   debugImplementation 'io.github.lygttpod:monitor:0.0.4'

-备注: 使用debugImplementation是为了只在测试环境中引入

2、monitor-plugin接入

  1. 根目录build.gradle下添加如下依赖
    buildscript {
        dependencies {
            ......
            //monitor-plugin需要
            classpath 'io.github.lygttpod:monitor-plugin:0.0.1'
        }
    }

2.添加插件

    在APP的build.gradle中添加:

    //插件内部会自动判断debug模式下hook到okhttp
    apply plugin: 'monitor-plugin'

原则上完成以上两步你的APP就成功集成了抓包工具,很简单有没有,如需定制化服务请看下边的个性化配置

3、 个性化配置

1、修改桌面抓包工具入口名字:在主项目string.xml中添加 monitor_app_name即可,例如:
```
   <string name="monitor_app_name">XXX-抓包</string>
```
2、定制抓包入口logo图标:
```
   添加 monitor_logo.png 即可
```
3、单个项目使用的话,添加依赖后可直接使用,无需初始化,库里会通过ContentProvider方式自动初始化
 
默认端口8080(端口号要唯一)
    
4、多个项目都集成抓包工具,需要对不同项目设置不同的端口和数据库名字,用来做区分
    
在主项目assets目录下新建 monitor.properties 文件,文件内如如下:对需要变更的参数修改即可
```
    # 抓包助手参数配置
    # Default port = 8080
    # Default dbName = monitor_db
    # ContentTypes白名单,默认application/json,application/xml,text/html,text/plain,text/xml
    # Default whiteContentTypes = application/json,application/xml,text/html,text/plain,text/xml
    # Host白名单,默认全部是白名单
    # Default whiteHosts = 
    # Host黑名单,默认没有黑名单
    # Default blackHosts = 
    # 如何多个项目都集成抓包工具,可以设置不同的端口进行访问
    monitor.port=8080
    monitor.dbName=app_name_monitor_db
```

4、 proguard(默认已经添加混淆,如遇到问题可以添加如下混淆代码)

```
    # monitor
    -keep class com.lygttpod.monitor.** { *; }
```

5、 温馨提示

    虽然monitor-plugin只会在debug环境hook代码,
    但是release版编译的时候还是会走一遍Transform操作(空操作),
    为了保险起见建议生产包禁掉此插件。

    在jenkins打包机器的《生产环境》的local.properties中添加monitor.enablePlugin=false,全面禁用monitor插件

6、如何使用

  • 集成之后编译运行项目即可在手机上自动生成一个抓包入口的图标,点击即可打开可视化页面查看网络请求数据,这样就可以随时随地的查看我们的请求数据了。
  • 虽然可以很方便的查看请求数据了但是手机屏幕太小,看起来不方便怎么办呐,那就去寻找在PC上展示的方法,首先想到的是能不能直接在浏览器里边直接看呐,这样不用安装任何程序在浏览输入一个地址就可以直接查看数据
  • PC和手机在同一局域网的前提下:直接在任意浏览器输入 手机ip地址+抓包工具设置的端口号即可(地址可以在抓包app首页TitleBar上可以看到)

五、原理介绍

①、 拦截APP的OKHTTP请求(添加拦截器处理抓包请求,使用ASM字节码插装技术实现)

  • 写一个Interceptor拦截器,获取请求及响应的数据,转化为需要的数据结构
override fun intercept(chain: Interceptor.Chain): Response {
    val request = chain.request()
    if (!MonitorHelper.isOpenMonitor) {
        return chain.proceed(request)
    }
    val monitorData = MonitorData()
    monitorData.method = request.method
    val url = request.url.toString()
    monitorData.url = url
    if (url.isNotBlank()) {
        val uri = Uri.parse(url)
        monitorData.host = uri.host
        monitorData.path = uri.path + if (uri.query != null) "?" + uri.query else ""
        monitorData.scheme = uri.scheme
    }
    ......以上为部分代码展示
}
  • 有了拦截器就可以通过字节码插桩技术在编译期自动为OKHTTP添加拦截器了,避免了使用者自己添加拦截器的操作
        mv?.let {
            it.visitVarInsn(ALOAD, 0)
            it.visitFieldInsn(GETFIELD, "okhttp3/OkHttpClient\$Builder", "interceptors", "Ljava/util/List;")
            it.visitFieldInsn(GETSTATIC, "com/lygttpod/monitor/MonitorHelper", "INSTANCE", "Lcom/lygttpod/monitor/MonitorHelper;")
            it.visitMethodInsn(INVOKEVIRTUAL, "com/lygttpod/monitor/MonitorHelper", "getHookInterceptors", "()Ljava/util/List;", false)
            it.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "addAll", "(Ljava/util/Collection;)Z", true)
            it.visitInsn(POP)
        }

②、 数据保存到本地数据库(room)

  • 数据库选择官方推荐Room进行数据操作
@Dao
interface MonitorDao {
    @Query("SELECT * FROM monitor WHERE id > :lastId ORDER BY id DESC")
    fun queryByLastIdForAndroid(lastId: Long): LiveData<MutableList<MonitorData>>

    @Query("SELECT * FROM monitor ORDER BY id DESC LIMIT :limit OFFSET :offset")
    fun queryByOffsetForAndroid(limit: Int, offset: Int): LiveData<MutableList<MonitorData>>

    @Query("SELECT * FROM monitor")
    fun queryAllForAndroid(): LiveData<MutableList<MonitorData>>

    @Query("SELECT * FROM monitor WHERE id > :lastId ORDER BY id DESC")
    fun queryByLastId(lastId: Long): MutableList<MonitorData>

    @Query("SELECT * FROM monitor ORDER BY id DESC LIMIT :limit OFFSET :offset")
    fun queryByOffset(limit: Int, offset: Int): MutableList<MonitorData>

    @Query("SELECT * FROM monitor")
    fun queryAll(): MutableList<MonitorData>

    @Insert
    fun insert(data: MonitorData)

    @Update
    fun update(data: MonitorData)

    @Query("DELETE FROM monitor")
    fun deleteAll()
}

③、 APP本地开启一个socket服务 AndroidLocalService

  • AndroidLocalService基于NanoHttpd实现的一个本地微服务库,底层是通过socket实现,同时使用注解加上javapoet框架自动生成模版代码,这样就可以很方便的创建服务了,下边是创建服务并启动服务示例代码
   //@Service标记这是一个服务,端口号是服务器的端口号,注意端口号唯一
   @Service(port = 9527)
   abstract class AndroidService {
   
       //@Page标注页面类,打开指定h5页面
       @Page("index")
       fun getIndexFileName() = "test_page.html"
       
       //@Get注解在方法上边
       @Get("query")
        fun query(aaa: Boolean, bbb: Double, ccc: Float, ddd: String, eee: Int,): List<String> {
            return listOf("$aaa", "$bbb", "$ccc", "$ddd", "$eee")
        }
    
       @Get("saveData")
       fun saveData(content: String) {
           LiveDataHelper.saveDataLiveData.postValue(content + UUID.randomUUID());
       }
   
       @Get("queryAppInfo")
       fun getAppInfo(): HashMap<String, Any> {
           return hashMapOf(
               "applicationId" to BuildConfig.APPLICATION_ID,
               "versionName" to BuildConfig.VERSION_NAME,
               "versionCode" to BuildConfig.VERSION_CODE,
               "uuid" to UUID.randomUUID(),
           )
       }
   }
   
   //初始化
   ALSHelper.init(this)
   //启动服务
   ALSHelper.startService(ServiceConfig(AndroidService::class.java))
   
   
   然后就可以通过 ip地址 + 端口号 访问了,例如:http://172.18.41.157:9527/index
   

使用 AndroidLocalService之后创建和启动服务就是这么简单有没有,具体用法及细节请查看其说明文档

④、 与本地socket服务通信

  • 剩下的就是与服务器的通信了,无论使用前端使用aJax还是客户端使用okhttp都可以正常请求数据了

⑤、 UI展示数据(手机端和PC端)

  • 有了接口和数据具体展示就看可以随意定制了,如果你不喜欢默认的UI风格,那就拉源码自己定制UI哦

六、最后

建议大家先下载demo体验体验,如果觉得方便易用就可以在项目中集成哦,在使用 AndroidMonitor过程遇到任何问题欢迎提Issues,如果对你有帮助,希望动动你的发财小手 点个赞呗吧!

代做工资流水公司长春工资银行流水打印惠州对公流水开具柳州企业对公流水费用贵阳代办流水账单舟山查询对公流水漳州公司银行流水模板金华打印个人银行流水太原工资流水图片曲靖查房贷收入证明赣州查薪资流水单淮安车贷工资流水 制作潍坊消费贷流水价格太原薪资银行流水湖州做公司流水长春签证工资流水代做三亚签证工资流水报价武汉银行对公流水报价淮安打印背调流水北京工资代付流水样本荆州工资流水公司蚌埠企业银行流水包头查企业流水打印信阳银行流水账芜湖打车贷银行流水汕头房贷收入证明打印滁州入职流水代办珠海代办银行流水单青岛银行流水开具兰州公司银行流水制作赣州自存银行流水图片香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声卫健委通报少年有偿捐血浆16次猝死汪小菲曝离婚始末何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言男子被猫抓伤后确诊“猫抓病”周杰伦一审败诉网易中国拥有亿元资产的家庭达13.3万户315晚会后胖东来又人满为患了高校汽车撞人致3死16伤 司机系学生张家界的山上“长”满了韩国人?张立群任西安交通大学校长手机成瘾是影响睡眠质量重要因素网友洛杉矶偶遇贾玲“重生之我在北大当嫡校长”单亲妈妈陷入热恋 14岁儿子报警倪萍分享减重40斤方法杨倩无缘巴黎奥运考生莫言也上北大硕士复试名单了许家印被限制高消费奥巴马现身唐宁街 黑色着装引猜测专访95后高颜值猪保姆男孩8年未见母亲被告知被遗忘七年后宇文玥被薅头发捞上岸郑州一火锅店爆改成麻辣烫店西双版纳热带植物园回应蜉蝣大爆发沉迷短剧的人就像掉进了杀猪盘当地回应沈阳致3死车祸车主疑毒驾开除党籍5年后 原水城县长再被查凯特王妃现身!外出购物视频曝光初中生遭15人围殴自卫刺伤3人判无罪事业单位女子向同事水杯投不明物质男子被流浪猫绊倒 投喂者赔24万外国人感慨凌晨的中国很安全路边卖淀粉肠阿姨主动出示声明书胖东来员工每周单休无小长假王树国卸任西安交大校长 师生送别小米汽车超级工厂正式揭幕黑马情侣提车了妈妈回应孩子在校撞护栏坠楼校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变老人退休金被冒领16年 金额超20万西藏招商引资投资者子女可当地高考特朗普无法缴纳4.54亿美元罚金浙江一高校内汽车冲撞行人 多人受伤

代做工资流水公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化