歡迎您光臨本站 註冊首頁

JAVA HTTP反向代理實現過程詳解

←手機掃碼閱讀     madbeef @ 2020-07-01 , reply:0

 反向代理(Reverse Proxy)方式是指以代理服務器來接受internet上的連接請求,然後將請求轉發給內部網絡上的服務器,並將從服務器上得到的結果返回給internet上請求連接的客戶端,此時代理服務器對外就表現為一個反向代理服務器。

 簡單來說,你的反向代理服務器會接收請求,但其自身不處理該請求,而是對請求經過一些處理,例如添加日誌、緩存、身份驗證等服務,然後再將請求轉發到相應的應用服務器中進行處理,最後將處理結果返回。

我目前的需求是,A應用需要訪問B應用的報表頁面,B應用沒有源碼,要求自動處理B應用的登錄權限。避免用戶重複登錄。

1. 引入相關依賴

  org.mitre.dsmiley.httpproxysmiley-http-proxy-servlet1.11

 

這個jar包,只有兩個類,其中核心的就是 ProxyServlet,
 

作者重寫了HttpServlet的相關方法。他複製了新的request為proxyRequest,
 

然後替換了地址和相關屬性,並使用HttpClient將proxyRequest發送出去,
 

然後將接收到的proxyResponse的內容再複製給 HttpResponse 。
 

相當於中轉站。具體請看源碼。
 

https://github.com/mitre/HTTP-Proxy-Servlet
 

2.spring使用:
 

2.1 application.yml增加代理參數配置
 

  # 設置代理  proxy:   servlet_url: /webappB/*   target_url: https://webappB_HOST_IP:8001/webappB其他demo   # servlet_url: /proxybaidu/*   # target_url: https://www.baidu.com

 

此處有玄機:
 

為什麼源url和目標url根路徑要一致(都為/webappB/)呢?
 

這是因為: target_url頁面裡不止文本顯示,還有其他資源的調用,比如圖片,比如裡面的js又調用了其他url.
 

這樣的話,假如 target頁面裡某個圖片的url是相對路徑 img/test.jpg;
 

你的頁面上圖的 /webappC/image/test.jpg; 這樣host換了以後是找不到圖片地址的。
 

當然你也可以改下proxyServlet的源碼,讓它換成正確的url地址。如果不想改源碼的話,那還是一致的比較好。少麻煩。

2.2 註冊servlet.
 

  @Configuration  public class ProxyServletConfiguration {    /**     * 讀取配置文件中路由設置     */    @Value("${proxy.servlet_url}")    private String servlet_url;    /**     * 讀取配置中代理目標地址     */    @Value("${proxy.target_url}")    private String target_url;      @Bean    public Servlet createProxyServlet() {      /** 創建新的ProxyServlet */      return new ProxyServlet();    }      @Bean    public ServletRegistrationBean proxyServletRegistration() {      ServletRegistrationBean registrationBean = new ServletRegistrationBean(createProxyServlet(), servlet_url);      //設置網址以及參數      Mapparams = ImmutableMap.of("targetUri", target_url, "log", "true");      registrationBean.setInitParameters(params);      return registrationBean;    }  }

 

2.3測試。ok.
 

localhost:8080/proxybaidu/

2.4. 當然你也可以重新寫個類,MyProxyServlet繼承ProxyServlet.
 

重新其中的 execute方法。添加相關的功能。日誌,權限登錄等。
 

  @Override    protected HttpResponse (HttpServletRequest servletRequest, HttpServletResponse servletResponse,                     HttpRequest proxyRequest) throws IOException {          //設置header裡的授權信息      proxyRequest.setHeader("Authorization", "Basic " + getWebappBLoginAuth());      HttpResponse response = super.doExecute(servletRequest, servletResponse, proxyRequest);    //    設置跨域,暫時不用。  //    String origin = servletRequest.getHeader("origin");  //    response.setHeader("Access-Control-Allow-Origin", origin);  //     response.setHeader("Access-Control-Allow-Credentials", "true");  //    response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");  //    response.setHeader("Access-Control-Allow-Headers",  //        "Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin" +  //            ",User-Agent,X-Mx-ReqToken,X-Requested-With");      return response;    }

 

2.5 後記

這個ProxyServlet 跟 nginx看著基本功能一樣了,都可以反向代理了。
 不過擴展功能和IO性能肯定跟nginx沒法比。但是這個是用java語言寫的。
 方便二次開發。


[madbeef ] JAVA HTTP反向代理實現過程詳解已經有104次圍觀

http://coctec.com/docs/java/show-post-240534.html