首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 應用程式透過 Proxy 存取網路完整指南

     編輯:Java 相關知識

前言:企業網路環境下的必修課

絕大多數企業為安全考量,內部網路不直接連通公網,需透過 Proxy Server (代理伺服器) 轉發 HTTP/HTTPS/FTP 流量。Java 應用若未正確配置 Proxy,將拋出 ConnectException: Connection timed out 或 UnknownHostException。本文彙整 JDK 內建系統屬性配置、認證處理、SOCKS 代理、各協定差異及版本相容性陷阱,助你一次解決所有代理問題。

核心系統屬性配置 (HTTP/HTTPS)

在建立任何 URL、HttpURLConnection、Socket 連線之前,設定下列系統屬性:

System.setProperty("http.proxyHost", "proxy.mycompany.com");
System.setProperty("http.proxyPort", "8080");
System.setProperty("https.proxyHost", "proxy.mycompany.com");
System.setProperty("https.proxyPort", "8080");

// 選項:繞過代理的主機/網域 (JDK 1.5+)
System.setProperty("http.nonProxyHosts", "localhost|127.0.0.1|*.mycompany.com");

注意:proxySet、proxyHost、proxyPort 為舊版 (JDK 1.1/1.2) 寫法,現代 JDK 僅建議使用 http.proxyHost 等標準屬性。舊屬性可能在某些版本失效。

Proxy 認證處理 (Basic Auth)

若代理需帳密驗證,需在 HttpURLConnection 請求頭加入 Proxy-Authorization:

String username = "user";
String password = "pass";
String auth = username + ":" + password;
String encoded = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.ISO_8859_1));
// 或使用 JDK 內建 sun.misc.BASE64Encoder (非標準 API)
// String encoded = new sun.misc.BASE64Encoder().encode(auth.getBytes());

URL url = new URL("https://example.com");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Proxy-Authorization", "Basic " + encoded);

關鍵點:Header 值必須以 Basic 開頭 (區分大小寫),後接 Base64 編碼字串。編碼時建議用 ISO-8859-1 避免中文亂碼。

FTP 協定代理配置

System.setProperty("ftp.proxyHost", "proxy.mycompany.com");
System.setProperty("ftp.proxyPort", "2121");
// JDK 無 ftp.nonProxyHosts,若需直連需自行判斷或用 SOCKS

使用方式同 HTTP:new URL("ftp://ftp.example.com/file.txt").openStream()。

SOCKS 代理 (SOCKS4/5) 全域生效

SOCKS 在 TCP 層轉發,對所有 TCP Socket 生效 (含 HTTP、FTP、自訂協定):

System.setProperty("socksProxyHost", "socks.mycompany.com");
System.setProperty("socksProxyPort", "1080"); // 預設 1080
// SOCKS5 支援認證需搭配 Authenticator
Authenticator.setDefault(new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication("socksUser", "socksPass".toCharArray());
    }
});

優先序:若同時設定 http.proxyHost 與 socksProxyHost,HTTP/HTTPS 走 HTTP Proxy;其他 TCP 走 SOCKS。若需強制 HTTP 走 SOCKS,可不設 HTTP Proxy 僅設 SOCKS。

程式碼層級精確控制 (Proxy 類別, JDK 1.5+)

不想汙染全域系統屬性?針對單一連線指定 Proxy:

Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.host", 8080));
URL url = new URL("https://example.com");
HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
// 或 Socket
Socket socket = new Socket(proxy);
socket.connect(new InetSocketAddress("target.host", 80));

此法優先於系統屬性,適合多租戶、動態切換代理場景。

常見坑點與版本差異

問題原因解決方案
JDK 1.1.7 / WebSphere 3.0 系統屬性無效舊版實作缺陷使用 new URL(protocol, host, port, file, handler) 建構子傳入 Proxy 主機/埠口,或升級 JDK
HTTPS 走代理但憑證驗證失敗代理執行 SSL 攔截 (MITM)將代理 CA 憑證匯入 JVM truststore (cacerts),或實作信任所有憑證的 TrustManager (僅測試用)
非標準埠口 HTTP 連線被代理攔截代理僅允許 80/443/8080聯繫網管開放埠口,或改用 SOCKS/SSH Tunnel
Proxy-Authorization 憑證包含特殊字元Base64 編碼前未正確處理嚴格遵循 RFC 7617:`user:pass` 用 ISO-8859-1 編碼後 Base64

最佳實務清單

  1. 啟動參數注入:生產環境建議用 `-Dhttp.proxyHost=... -Dhttp.proxyPort=...` 啟動 JVM,避免程式碼硬編碼。
  2. 統一配置類:封裝 ProxyConfig 類,集中管理 HTTP/HTTPS/FTP/SOCKS 設定與認證。
  3. 連線測試:應用啟動時主動向已知站點 (如 https://www.google.com) 發送 HEAD 請求驗證代理通暢。
  4. 日誌記錄:記錄實際使用的 Proxy 類型、位址、認證狀態,利於除錯。

總結

Java 代理支援機制成熟但細節多。核心原則:盡早設定系統屬性或使用 Proxy 類別、正確處理 Basic Auth Header、區分 HTTP/SOCKS 適用場景、注意版本相容性。掌握這些,無論是爬蟲、微服務呼叫、Maven/Gradle 依賴下載,都能在企業網路環境暢行無阻。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved