您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關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請求,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。