如何劫持Java應(yīng)用的HTTP請(qǐng)求
背景
全鏈路追蹤中,針對(duì)部分特殊的流量,希望將它引導(dǎo)到特定服務(wù)上(這個(gè)特定服務(wù)不在正常請(qǐng)求的鏈路上)——問(wèn)題可以被抽象為解決進(jìn)程間通信過(guò)程中目標(biāo)進(jìn)程的選擇。
進(jìn)程間通信方式很多,本篇只關(guān)注 Java 進(jìn)程間套接字通信下 HTTP 形式的請(qǐng)求劫持,引導(dǎo)特定流量到特定進(jìn)程。
解決方案
可行的處理方案繁多。自頂向下從應(yīng)用、框架、JVM、Container Runtime、System Call、網(wǎng)絡(luò)協(xié)議棧等級(jí)別,均可著手解決。侵入性最強(qiáng)的操作就是要求所有業(yè)務(wù)應(yīng)用都主動(dòng)實(shí)現(xiàn) HTTP 請(qǐng)求分流邏輯;次一級(jí)是提供二方庫(kù)供業(yè)務(wù)應(yīng)用主動(dòng)集成;或者從系統(tǒng)層面進(jìn)行改造,基于改寫(xiě)系統(tǒng)調(diào)用對(duì)請(qǐng)求進(jìn)行劫持。
回顧兩年前的所學(xué),JVM TI 為劫持 HTTP 請(qǐng)求提供了一個(gè)全新的解決思路。通過(guò) Agent 改寫(xiě)應(yīng)用啟動(dòng)時(shí)加載的類的字節(jié)碼,劫持類的實(shí)例并完成目標(biāo)功能。
由于 Java 項(xiàng)目間調(diào)用大量的使用了 Apache 的 http-client 庫(kù),改寫(xiě)變得相當(dāng)簡(jiǎn)單。識(shí)別流量,并對(duì)特定流量改寫(xiě)請(qǐng)求的 Host 即可。
Demo
由于 http-client 對(duì)所有請(qǐng)求目標(biāo)都統(tǒng)一由 org.apache.http.HttpHost
維護(hù),控制變得極為簡(jiǎn)單。只需在 HttpHost
實(shí)例化時(shí),改寫(xiě)類的構(gòu)造方法,即完成了對(duì)目標(biāo)的劫持工作(下例中強(qiáng)制將所有請(qǐng)求指向 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; } }
將整個(gè)項(xiàng)目打包為 agent.jar 的過(guò)程不做太多介紹,詳見(jiàn) ffutop/http-client-plugin
針對(duì)需要劫持的項(xiàng)目,在啟動(dòng)參數(shù)中增加 -javaagent:${PATH_TO}/http-client-plugin.jar
以上就是如何劫持Java應(yīng)用的HTTP請(qǐng)求的詳細(xì)內(nèi)容,更多關(guān)于劫持Java應(yīng)用的HTTP請(qǐng)求的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot如何通過(guò)自定義注解實(shí)現(xiàn)權(quán)限檢查詳解
這篇文章主要給大家介紹了關(guān)于SpringBoot如何通過(guò)自定義注解實(shí)現(xiàn)權(quán)限檢查的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10springboot3.2整合mybatis-plus詳細(xì)代碼示例
這篇文章主要給大家介紹了關(guān)于springboot3.2整合mybatis-plus的相關(guān)資料,Spring Boot是一個(gè)非常流行的Java Web框架,可以快速地搭建Web應(yīng)用程序,需要的朋友可以參考下2023-12-12springboot+Oauth2實(shí)現(xiàn)自定義AuthenticationManager和認(rèn)證path
本篇文章主要介紹了springboot+Oauth2實(shí)現(xiàn)自定義AuthenticationManager和認(rèn)證path,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09Java實(shí)現(xiàn)創(chuàng)建運(yùn)行時(shí)類的對(duì)象操作示例
這篇文章主要介紹了Java實(shí)現(xiàn)創(chuàng)建運(yùn)行時(shí)類的對(duì)象操作,結(jié)合實(shí)例形式分析了Java動(dòng)態(tài)創(chuàng)建對(duì)象的原理與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2018-08-08IDEA 項(xiàng)目創(chuàng)建Mapper的xml文件的方法
這篇文章主要介紹了IDEA 項(xiàng)目創(chuàng)建Mapper的xml文件的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11SpringBoot中@PostConstruct 注解的實(shí)現(xiàn)
在Spring Boot框架中,?@PostConstruct是一個(gè)非常有用的注解,它用于在依賴注入完成后執(zhí)行初始化方法,本文將介紹?@PostConstruct的基本概念、使用場(chǎng)景以及提供詳細(xì)的代碼示例,感興趣的可以了解一下2024-09-09Spring Boot中利用JavaMailSender發(fā)送郵件的方法示例(附源碼)
這篇文章主要介紹了Spring Boot中利用JavaMailSender發(fā)送郵件的方法示例, 相信使用過(guò)Spring的眾多開(kāi)發(fā)者都知道Spring提供了非常好用的JavaMailSender接口實(shí)現(xiàn)郵件發(fā)送。在Spring Boot的Starter模塊中也為此提供了自動(dòng)化配置。需要的朋友可以參考借鑒。2017-02-02java實(shí)現(xiàn)大文件分割與合并的實(shí)例代碼
java實(shí)現(xiàn)大文件分割與合并的實(shí)例代碼,需要的朋友可以參考一下2013-03-03