1. 程式人生 > 程式設計 >JAVA HTTP反向代理實現過程詳解

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

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

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

我目前的需求是,A應用需要訪問B應用的報表頁面,B應用沒有原始碼,要求自動處理B應用的登入許可權。避免使用者重複登入。

1. 引入相關依賴

<dependency>
  <groupId>org.mitre.dsmiley.httpproxy</groupId>
  <artifactId>smiley-http-proxy-servlet</artifactId>
  <version>1.11</version>
</dependency>

這個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);
    //設定網址以及引數
    Map<String,String> params = 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語言寫的。
方便二次開發。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。