AsmActualCombat
- 项目地址:https://github.com/Peakmain/AsmActualCombat
- 使用文档链接:https://github.com/Peakmain/AsmActualCombat/wiki
前言
相关文章系列
- Gradle 插件 + ASM 实战——入门篇
- Gradle+ASM实战——进阶篇
- Gradle+ASM实战——隐私方法问题彻底解决之AsmActualCombat开源库
- 隐私政策整改之Glide框架封装
ASM文档
需求背景
- 上篇文章我们讲了关于图片加载获取应用自身获取个人信息行为问题修复。其实还有其他的也会获取User-Agent,如网络行为,webView获取User-Agent
- webView解决方法就是不要调用下面方法
webSettings.getUserAgentString()
- 网络行为如果是自身的就比较简单,一般情况来说,我们都是用OKhttp(Retrofit可以理解只是对okHttp的进行封装的架构库,底层还是OkHttp)去请求网络,那么直接去移除相关Header,或者直接设置一个通用的值如:Android即可
private static Interceptor addCommonParameterInterceptor() {
return chain -> {
Request originalRequest = chain.request();
Request newRequest = originalRequest.newBuilder()
.url(modifiedUrl.build()).removeHeader("User-Agent").addHeader("User-Agent",
"Android").build();
return chain.proceed(newRequest);
};
}
- 还有的公司请求可能用的还是HttpUrlConnection,关于这个怎么拦截,大家往下看。
-
我们今天主要讲的是怎么去拦截第三方库或者jar包的网络请求,我们首先看几张图
- 上面三张图分别是七牛云,高德,mob分享sdk三个库的网络请求,我们会发现他们在User-Agent中获取应用自身获取个人信息行为(黄色区域)
- 今天我们的目标就是怎么把它替换成固定的值Android或者删除
- 我们今天主要对七牛云进行分析拦截,其它的基本大同小异
七牛云网络网络分析
- 目标:找到它们设置User-Agent代码
- 源码位置:https://github.com/Peakmain/AsmActualCombat/blob/master/plugin/src/main/groovy/com/peakmain/analytics/plugin/visitor/NetworkMethodCalledReplaceAdapter.groovy
- 我们在APP一般需要添加依赖
implementation 'com.qiniu:qiniu-android-sdk:7.3.15'
-
找到七牛云源码的位置
- 我们可以一个个点哈,也可以看名字猜哈,我们可以直接看Client代码
public Client(ProxyConfiguration proxy, int connectTimeout, int responseTimeout, UrlConverter converter, final Dns dns) {
this.converter = converter;
OkHttpClient.Builder builder = new OkHttpClient.Builder();
//代码省略
builder.connectTimeout(connectTimeout, TimeUnit.SECONDS);
builder.readTimeout(responseTimeout, TimeUnit.SECONDS);
builder.writeTimeout(0, TimeUnit.SECONDS);
httpClient = builder.build();
}
我们可以发现七牛云用的是okHttp哈,当然这不是重点,但是大家在做自己项目的时候,可以参考下大厂是怎么做的封装的。
- 既然是OkHttp,一定是通过request.addHeader方式,我们直接搜User-Agent
if (upToken != null) {
requestBuilder.header("User-Agent", UserAgent.instance().getUa(upToken.accessKey));
} else {
requestBuilder.header("User-Agent", UserAgent.instance().getUa("pandora"));
}
- 还有其他几个地方引用,代码差不多,就贴上面两个,我们会发现,它们都是调用同一个方法UserAgent的getUa方法
- 如果我们将UserAgent的getUa方法的返回值设为空字符串或者某个固定的值是不是就解决了
- 我们直接在visitMethodInsn方法体中找到com.qiniu.android.http.UserAgent的getUa方法
void visitMethodInsn(int opcodeAndSource, String owner, String name, String descriptor, boolean isInterface) {
String qi_niu_yun="com/qiniu/android/http/UserAgent"+"getUa"+"(Ljava/lang/String;)Ljava/lang/String;"
String desc = owner + name + descriptor
if(qi_niu_yun==desc){
}
}
- 找到方法之后在方法体通过super.visitMethodInsn替换成我们自己的方法
- 自己设置类和方法:如下
package com.peakmain.sdk.utils.network;
/**
* author :Peakmain
* createTime:2022/6/14
* mail:2726449200@qq.com
* describe:
*/
public class UserAgent {
public static String getUa(com.qiniu.android.http.UserAgent userAgent, String part) {
return "";
}
}
所以我们替换后的owner是:
public static final String OWNER_NEW_QI_NIU_HTTP_USER_AGENT = "com/peakmain/sdk/utils/network/UserAgent"
name:
public static final String NAME_QI_NIU_HTTP_USER_AGENT = "getUa"
desc
public static final String DESCRIPTOR_NEW_QI_NIU_HTTP_USER_AGENT = "(Lcom/qiniu/android/http/UserAgent;Ljava/lang/String;)Ljava/lang/String;"
这里解释下,为什么要添加七牛云的UserAgent对象,因为七牛云本身获取User-Agent用的是UserAgent的非静态方法,非静态方法持有了UserAgent对象,所以我们需要将它消费掉
- 替换或的方法
void visitMethodInsn(int opcodeAndSource, String owner, String name, String descriptor, boolean isInterface) {
String qi_niu_yun="com/qiniu/android/http/UserAgent"+"getUa"+"(Ljava/lang/String;)Ljava/lang/String;"
String desc = owner + name + descriptor
if(qi_niu_yun==desc){
super.visitMethodInsn(Opcodes.INVOKESTATIC, OWNER_NEW_QI_NIU_HTTP_USER_AGENT, NAME_QI_NIU_HTTP_USER_AGENT,DESCRIPTOR_NEW_QI_NIU_HTTP_USER_AGENT, false)
}else{
super.visitMethodInsn(opcodeAndSource, owner, name, descriptor, isInterface)
}
}
- 至此替换就完成了,代码还是非常简单的。
总结
- 七牛云的网络请求主要通过Okhttp去请求的,并且它们设置User-Agent用的是一个单例的UserAgent的getUa方法,我们只需要拦截这个方法并将其即可
- 关于HttpUrlConnection的头部拦截,大家可以直接将header清空,或者直接将header进行替换。
-
关于Mob它们的网络请求,大家可以看NetworkHelper类即可