如何劫持Java应用的HTTP请求
背景
全链路追踪中,针对部分特殊的流量,希望将它引导到特定服务上(这个特定服务不在正常请求的链路上)——问题可以被抽象为解决进程间通信过程中目标进程的选择。
进程间通信方式很多,本篇只关注 Java 进程间套接字通信下 HTTP 形式的请求劫持,引导特定流量到特定进程。
解决方案
可行的处理方案繁多。自顶向下从应用、框架、JVM、Container Runtime、System Call、网络协议栈等级别,均可着手解决。侵入性最强的操作就是要求所有业务应用都主动实现 HTTP 请求分流逻辑;次一级是提供二方库供业务应用主动集成;或者从系统层面进行改造,基于改写系统调用对请求进行劫持。
回顾两年前的所学,JVM TI 为劫持 HTTP 请求提供了一个全新的解决思路。通过 Agent 改写应用启动时加载的类的字节码,劫持类的实例并完成目标功能。
由于 Java 项目间调用大量的使用了 Apache 的 http-client 库,改写变得相当简单。识别流量,并对特定流量改写请求的 Host 即可。
Demo
由于 http-client 对所有请求目标都统一由 org.apache.http.HttpHost 维护,控制变得极为简单。只需在 HttpHost 实例化时,改写类的构造方法,即完成了对目标的劫持工作(下例中强制将所有请求指向 163.com)
public class Agent implements ClassFileTransformer {
public static void premain(String args, Instrumentation instrumentation) {
instrumentation.addTransformer(new Agent());
}
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
if ("org/apache/http/HttpHost".equals(className)) {
ClassPool pool = ClassPool.getDefault();
try {
CtClass httpHost = pool.get("org.apache.http.HttpHost");
CtClass string = pool.get("java.lang.String");
CtConstructor constructor = httpHost.getDeclaredConstructor(new CtClass[]{string, CtClass.intType, string});
constructor.insertBefore("hostname = \"www.163.com\";");
byte[] bytes = httpHost.toBytecode();
FileOutputStream fos = new FileOutputStream("/Users/fangfeng/a.class");
fos.write(bytes);
return bytes;
} catch(NotFoundException | CannotCompileException | IOException e){
e.printStackTrace();
}
}
return classfileBuffer;
}
}
将整个项目打包为 agent.jar 的过程不做太多介绍,详见 ffutop/http-client-plugin
针对需要劫持的项目,在启动参数中增加 -javaagent:${PATH_TO}/http-client-plugin.jar
以上就是如何劫持Java应用的HTTP请求的详细内容,更多关于劫持Java应用的HTTP请求的资料请关注脚本之家其它相关文章!
相关文章
Mybatis配置之<typeAliases>别名配置元素解析
这篇文章主要介绍了Mybatis配置之<typeAliases>别名配置元素解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-07-07
SpringMVC中controller接收json数据的方法
这篇文章主要为大家详细介绍了SpringMVC中controller接收json数据的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2017-09-09
Java位集合之BitMap、BitSet和布隆过滤器示例解析
这篇文章主要介绍了Java中位集合的基本概念、实现方法以及应用场景,包括Bit-Map、BitSet和BloomFilter,Bit-Map通过位操作高效地存储和查询元素状态,文中通过代码介绍的非常详细,需要的朋友可以参考下2024-12-12
详解springboot springsecuroty中的注销和权限控制问题
这篇文章主要介绍了springboot-springsecuroty 注销和权限控制,账户注销需要在SecurityConfig中加入开启注销功能的代码,权限控制要导入springsecurity和thymeleaf的整合依赖,本文通过实例代码给大家介绍的非常详细,需要的朋友参考下吧2022-03-03


最新评论