打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
AndroidMonitor抓包原理及使用方法
userphoto

2022.09.10 广东

关注
1
Android抓包现状

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

https://github.com/lygttpod/AndroidMonitor


2
效果展示

俗话说无图无真相


3
如何使用

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


源码地址:

https://github.com/lygttpod/AndroidMonitor

1.monitor接入

添加依赖

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

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

2.monitor-plugin接入

· 根目录build.gradle下添加如下依赖。

buildscript {
    dependencies {
        ......
        //monitor-plugin需要
        classpath 'io.github.lygttpod:monitor-plugin:0.0.1'
    }
}

· 添加插件。

在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上可以看到)。


4
原理介绍

1.拦截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)
}

2. 数据保存到本地数据库(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(dataMonitorData)

    @Update
    fun update(dataMonitorData)

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

3.APP本地开启一个socket服务AndroidLocalService

https://github.com/lygttpod/android-local-service

· 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之后创建和启动服务就是这么简单有没有,具体用法及细节请查看其说明文档。

4.与本地socket服务通信

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

5.UI展示数据(手机端和PC端)

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


链接:https://juejin.cn/post/7119083753376317448
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C4C Cloud Application Studio做ABSL开发的一些性能方面的最佳实践
ORACLE UCM 《Content Integration Suite 8.0.0开发指导》
Android 彻底组件化方案实践
在AngularJS中使用$q同步读取服务器数据
Tracing Enhancements Using DBMS_Monitor
ARouter 拦截器之多 module 独立运行
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服