HttpURLConnection
HttpURLConnection
是 Java 标准库中用于进行 HTTP 请求的类,它提供了一种简便的方式来通过 HTTP 协议与服务器进行通信。HttpURLConnection
属于 java.net
包,可以处理各种 HTTP 请求方法(如 GET、POST、PUT、DELETE 等),并支持 HTTPS 等功能。
基本概念和工作原理
HttpURLConnection
是一个抽象类,继承自 URLConnection
,它专门用于发起 HTTP 请求和接收响应。通过 HttpURLConnection
,你可以发送请求到指定的 URL,并读取服务器返回的响应。
基本工作流程:
建立连接:创建
HttpURLConnection
对象,指定请求的 URL。配置请求:设置 HTTP 请求方法(如 GET、POST)、请求头等。
发送请求:打开连接,发送请求内容。
处理响应:读取服务器的响应状态码和响应内容。
关闭连接:释放资源,关闭连接。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpURLConnectionExample {
public static void main(String[] args) {
try {
// 1. 创建 URL 对象
URL url = new URL("https://api.example.com/data");
// 2. 打开连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 3. 设置请求方法 (GET/POST/PUT/DELETE)
connection.setRequestMethod("GET");
// 4. 设置请求头(可选)
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
connection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
// 5. 发送请求并获取响应码
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
// 6. 读取响应内容
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// 7. 打印响应内容
System.out.println(response.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
HttpsURLConnection 的 GET 和 POST 请求
1 | package com.xiaojianbang.test; |
HttpsURLConnection 的自吐
先开启 objection 的 hook
1 | objection -g com.example.network explore |
1 | android hooking search classes HttpsURLConnection |
1 | android hooking watch class com.android.okhttp.internal.huc.HttpURLConnectionImpl |
1 | function hook_HttpUrlConnection(){ |
okhttp3
基础
OkHttp 是一个高效的 HTTP 和 HTTP/2 客户端,广泛用于 Android 和 Java 应用程序中。它由 Square 开发,提供了许多强大的功能和灵活的 API,适用于各种网络请求场景。
添加依赖
在 build.gradle
文件中添加 OkHttp 的依赖:
1 | implementation 'com.squareup.okhttp3:okhttp:4.10.0' |
创建 OkHttpClient
1 | OkHttpClient client = new OkHttpClient(); |
1 | java复制代码Interceptor loggingInterceptor = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY); |
发送 GET 请求
1 | Request request = new Request.Builder() |
发送 POST 请求
1 | RequestBody requestBody = new FormBody.Builder() |
添加拦截器
1 | Interceptor loggingInterceptor = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY); |
OkHttp3
的拦截器是一种可以在网络请求和响应过程中拦截、修改和处理 HTTP 请求和响应的机制。在 OkHttp 中,拦截器类似于一个过滤器,允许开发者在请求发出前或响应返回后执行自定义逻辑,从而实现日志记录、添加认证头、处理重试机制等功能。
拦截器主要分为两类:
- 应用拦截器(Application Interceptors)
- 网络拦截器(Network Interceptors)
应用拦截器(Application Interceptors)
应用拦截器会在整个请求和响应链条的顶端工作,并且只会被调用一次。它们可以用于修改最终请求和响应,还可以根据需要对请求进行重试或短路。应用拦截器不会处理来自缓存的响应,应用更适合用于日志记录、全局添加 Header、错误重试等场景。
添加应用拦截器示例:
1 | val client = OkHttpClient.Builder() |
网络拦截器(Network Interceptors)
网络拦截器在网络请求的过程中生效,每次 HTTP 请求都会调用它们,包括从缓存读取的请求。网络拦截器可以访问网络的实际响应状态、头信息等,更适用于监控和调试网络流量、处理缓存逻辑等。
添加网络拦截器示例:
1 | val client = OkHttpClient.Builder() |
如何使用多个拦截器
OkHttp 支持链式调用多个拦截器,拦截器按添加顺序依次执行。一个典型的应用是将应用拦截器用于预处理请求,而将网络拦截器用于网络流量的分析。
1 | val client = OkHttpClient.Builder() |
hook
自定义拦截器 hook
用 spawn 方式启动 app
frida -U –no-pause -f xxx -l hook.js
1 | function hook_okhttp3() { |
Frida 提供了如下 API 用于将 DEX 加载进内存,从而使用 DEX 中的方法和类,因为 DEX 是外来之物,因此称为天外飞仙。(需要注意的是,无法加载 JAR 包):
1 | Java.openClassFile(dexPath).load(); |
(1).解压 app-debug.apk 取出 classes1.dex 文件(其中有目标类)
(2).push 到/data/local/tmp 下
(3).修改 Frida Hook 代码:
1 | function hook_okhttp3() { |
(4).Frida Hook,在此之前将 DEMO 中 OKhttpclient 的添加拦截器代码注销,以防干扰,查看 Android Studio 日志,拦截器是否生效。
官方拦截器:(日志)
1 | package com.r0ysue.learnokhttp; |
Retrofit
Retrofit 是由 Square 公司开发的一个类型安全的 HTTP 客户端库,主要用于 Android 和 Java 应用程序,通过将 REST API 转化为 Java 接口,大大简化了网络请求的实现过程。Retrofit 使用动态代理、注解等机制,让网络请求的定义更直观,并通过与 Gson、Moshi 等序列化工具的集成,支持数据的自动解析与转换。Retrofit 就是 Ok3
所有搞 Ok3 的都可以搞 Retrofit
Retrofit 的核心工作原理
- 接口设计:在 Retrofit 中,每一个 HTTP 请求都通过一个 Java 接口的方法来定义。每个方法代表一个 API 端点,并通过注解来指定请求类型(如 GET、POST)和 URL 路径。
- 动态代理:Retrofit 使用动态代理模式实现接口定义的网络请求,简化了实际代码量。开发者仅需关注接口定义,无需手动实现网络请求。
- 数据解析与转换:Retrofit 支持多种序列化工具(如 Gson、Moshi)将 API 响应的 JSON 数据自动转换成 Java 对象,提升了代码的可维护性。
主要注解类型
@GET
、@POST
、@PUT
、@DELETE
等:指定 HTTP 请求方法类型。@Path
:用于 URL 路径参数的动态替换,例如/users/{userId}
。@Query
:用于在 URL 中添加查询参数,例如?key=value
。@Body
:用于 POST 请求的请求体数据。@FormUrlEncoded
和@Field
:用于表单编码请求(application/x-www-form-urlencoded
)。@Multipart
和@Part
:用于多部分请求,适用于文件上传等场景。@Headers
:用于指定静态的请求头信息。
构建 Retrofit 实例
使用 Retrofit.Builder
设置基础配置并生成 Retrofit 实例:
1 | Retrofit retrofit = new Retrofit.Builder() |
- **baseUrl()**:设置基础 URL,所有接口定义的相对 URL 会以此为基础。
- **addConverterFactory()**:添加解析器(如 Gson)以处理响应数据的解析。
- **client()**:可设置自定义的
OkHttpClient
,用来配置超时、缓存、日志拦截等。
API 接口定义
例如,假设我们需要从 https://api.example.com/users/{id}
获取用户信息,可以定义如下接口:
1 | public interface ApiService { |
然后使用 Retrofit 创建实例并调用方法:
1 | ApiService apiService = retrofit.create(ApiService.class); |
异步与同步请求
- 同步请求:通过
Call.execute()
来实现,但会阻塞当前线程,通常不推荐在主线程使用。 - 异步请求:通过
Call.enqueue()
实现,传入回调函数处理响应或错误,避免阻塞主线程。
数据解析
Retrofit 支持多种数据转换工厂(Converter Factory),常用的包括:
- GsonConverterFactory:将 JSON 响应转换成 Java 对象。
- MoshiConverterFactory:支持 Moshi 作为数据解析工具。
- ScalarsConverterFactory:直接将原始数据作为
String
或int
类型返回。
Retrofit 与 OkHttp
Retrofit 基于 OkHttp 构建,允许与 OkHttp 的拦截器、缓存机制、连接池等进行集成和优化。开发者可以通过自定义 OkHttpClient
来增强 Retrofit 的功能,比如添加日志拦截器、身份验证拦截器等。
Retrofit 基于 OkHttp 构建,允许与 OkHttp 的拦截器、缓存机制、连接池等进行集成和优化。开发者可以通过自定义 OkHttpClient
来增强 Retrofit 的功能,比如添加日志拦截器、身份验证拦截器等。
错误处理
Retrofit 提供 onFailure()
回调捕获请求异常。同时,响应对象的 isSuccessful()
方法可以判断请求是否成功,通常结合 try-catch
进行更细致的错误处理。
hook
1 | function hookbaseurl (){ |
SOCKET 自吐
1 | function hook_socket(){ |