簡體   English   中英

如何設置 JVM 使用的代理

[英]How do I set the proxy to be used by the JVM

很多時候,Java 應用程序需要連接到 Internet。 最常見的示例發生在讀取 XML 文件並需要下載其模式時。

我在代理服務器后面。 如何設置我的 JVM 以使用代理?

從 Java 文檔(不是javadoc API):

http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html

在命令行上啟動 JVM 時設置 JVM 標志http.proxyHosthttp.proxyPort 這通常在 shell 腳本(在 Unix 中)或 bat 文件(在 Windows 中)中完成。 這是 Unix shell 腳本的示例:

JAVA_FLAGS=-Dhttp.proxyHost=10.0.0.100 -Dhttp.proxyPort=8800
java ${JAVA_FLAGS} ...

在使用 JBoss 或 WebLogic 等容器時,我的解決方案是編輯供應商提供的啟動腳本。

許多開發人員都熟悉 Java API (javadocs),但很多時候文檔的其余部分被忽略了。 它包含很多有趣的信息:http: //download.oracle.com/javase/6/docs/technotes/guides/


更新:如果您不想使用代理來解析某些本地/內部網主機,請查看 @Tomalak 的評論:

也不要忘記 http.nonProxyHosts 屬性!

-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.example.com|etc"

要使用系統代理設置:

java -Djava.net.useSystemProxies=true ...

或以編程方式:

System.setProperty("java.net.useSystemProxies", "true");

來源: http ://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html

以編程方式設置 HTTP/HTTPS 和/或 SOCKS 代理:

...

public void setProxy() {
    if (isUseHTTPProxy()) {
        // HTTP/HTTPS Proxy
        System.setProperty("http.proxyHost", getHTTPHost());
        System.setProperty("http.proxyPort", getHTTPPort());
        System.setProperty("https.proxyHost", getHTTPHost());
        System.setProperty("https.proxyPort", getHTTPPort());
        if (isUseHTTPAuth()) {
            String encoded = new String(Base64.encodeBase64((getHTTPUsername() + ":" + getHTTPPassword()).getBytes()));
            con.setRequestProperty("Proxy-Authorization", "Basic " + encoded);
            Authenticator.setDefault(new ProxyAuth(getHTTPUsername(), getHTTPPassword()));
        }
    }
    if (isUseSOCKSProxy()) {
        // SOCKS Proxy
        System.setProperty("socksProxyHost", getSOCKSHost());
        System.setProperty("socksProxyPort", getSOCKSPort());
        if (isUseSOCKSAuth()) {
            System.setProperty("java.net.socks.username", getSOCKSUsername());
            System.setProperty("java.net.socks.password", getSOCKSPassword());
            Authenticator.setDefault(new ProxyAuth(getSOCKSUsername(), getSOCKSPassword()));
        }
    }
}

...

public class ProxyAuth extends Authenticator {
    private PasswordAuthentication auth;

    private ProxyAuth(String user, String password) {
        auth = new PasswordAuthentication(user, password == null ? new char[]{} : password.toCharArray());
    }

    protected PasswordAuthentication getPasswordAuthentication() {
        return auth;
    }
}

...

請記住,HTTP 代理和 SOCKS 代理在網絡堆棧中的不同級別運行,因此您可以使用其中一個或兩個或兩者。

您可以通過以下方式以編程方式設置這些標志:

if (needsProxy()) {
    System.setProperty("http.proxyHost",getProxyHost());
    System.setProperty("http.proxyPort",getProxyPort());
} else {
    System.setProperty("http.proxyHost","");
    System.setProperty("http.proxyPort","");
}

只需從方法needsProxy()getProxyHost()getProxyPort()中返回正確的值,您就可以隨時調用此代碼片段。

JVM 使用代理進行 HTTP 調用

System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");

這可能會使用用戶設置代理

System.setProperty("java.net.useSystemProxies", "true");

結合 Sorter 和 javabrett/Leonel 的答案:

java -Dhttp.proxyHost=10.10.10.10 -Dhttp.proxyPort=8080 -Dhttp.proxyUser=username -Dhttp.proxyPassword=password -jar myJar.jar

java.net.useSystemProxies屬性設置為true 例如,您可以通過JAVA_TOOL_OPTIONS環境變量來設置它。 例如,在 Ubuntu 中,您可以將以下行添加到.bashrc

導出 JAVA_TOOL_OPTIONS+="-Djava.net.useSystemProxies=true"

您可以將有關代理服務器的一些屬性設置為 jvm 參數

-Dhttp.proxyPort=8080、proxyHost等

但是如果您需要通過身份驗證代理,則需要像以下示例一樣的身份驗證器:

ProxyAuthenticator.java

import java.net.*;
import java.io.*;

public class ProxyAuthenticator extends Authenticator {

    private String userName, password;

    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(userName, password.toCharArray());
    }

    public ProxyAuthenticator(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }
}

Example.java

    import java.net.Authenticator;
    import ProxyAuthenticator;

public class Example {

    public static void main(String[] args) {
        String username = System.getProperty("proxy.authentication.username");
        String password = System.getProperty("proxy.authentication.password");

                if (username != null && !username.equals("")) {
            Authenticator.setDefault(new ProxyAuthenticator(username, password));
        }

                // here your JVM will be authenticated

    }
}

基於此回復:http: //mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/200208.mbox/%3C494FD350388AD511A9DD00025530F33102F1DC2C@MMSX006%3E

下面展示了如何在 Java 中從命令行使用代理用戶和代理密碼設置代理,這是一種非常常見的情況。 首先,您不應該在代碼中保存密碼和主機。

使用 -D 在命令行中傳遞系統屬性並使用 System.setProperty("name", "value") 在代碼中設置它們是等效的。

但請注意這一點

有效的例子:

C:\temp>java -Dhttps.proxyHost=host -Dhttps.proxyPort=port -Dhttps.proxyUser=user -Dhttps.proxyPassword="password" -Djavax.net.ssl.trustStore=c:/cacerts -Djavax.net.ssl.trustStorePassword=changeit com.andreas.JavaNetHttpConnection

但以下不起作用

C:\temp>java com.andreas.JavaNetHttpConnection -Dhttps.proxyHost=host -Dhttps.proxyPort=port -Dhttps=proxyUser=user -Dhttps.proxyPassword="password" -Djavax.net.ssl.trustStore=c:/cacerts -Djavax.net.ssl.trustStorePassword=changeit

唯一不同的是系統屬性的位置! (課前和課后)

如果您的密碼中有特殊字符,您可以將其放在引號“@MyPass123%”中,如上例所示。

如果您訪問 HTTPS 服務,則必須使用https.proxyHosthttps.proxyPort等。

如果您訪問 HTTP 服務,則必須使用http.proxyHosthttp.proxyPort等。

讀取 XML 文件並需要下載其架構

如果您指望通過 Internet 檢索模式或 DTD,那么您正在構建一個緩慢、健談、脆弱的應用程序。 當托管文件的遠程服務器發生計划內或計划外停機時會發生什么? 您的應用程序中斷。 那樣行嗎?

請參閱http://xml.apache.org/commons/components/resolver/resolver-article.html#s.catalog.files

架構等的 URL 最好被視為唯一標識符。 不像請求實際遠程訪問該文件。 在“XML 目錄”上做一些谷歌搜索。 XML 目錄允許您在本地托管此類資源,從而解決緩慢、繁瑣和脆弱的問題。

它基本上是遠程內容的永久緩存副本。 沒關系,因為遠程內容永遠不會改變。 如果有更新,它將位於不同的 URL。 通過互聯網實際檢索資源特別愚蠢。

如果您想要“Socks 代理”,請通知“socksProxyHost”和“socksProxyPort”VM 參數。

例如

java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main

我也在防火牆后面,這對我有用!

System.setProperty("http.proxyHost", "proxy host addr");
System.setProperty("http.proxyPort", "808");
Authenticator.setDefault(new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {

        return new PasswordAuthentication("domain\\user","password".toCharArray());
    }
});

URL url = new URL("http://www.google.com/");
URLConnection con = url.openConnection();

BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream()));

// Read it ...
String inputLine;
while ((inputLine = in.readLine()) != null)
    System.out.println(inputLine);

in.close();

在連接到代理后面的 URL 之前添加它。

System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");
System.getProperties().put("http.proxyUser", "someUserName");
System.getProperties().put("http.proxyPassword", "somePassword");

這是一個小更新,但從 Java 7 開始,代理連接現在可以通過編程而不是通過系統屬性來創建。 如果出現以下情況,這可能很有用:

  1. 代理需要在程序運行時動態旋轉
  2. 需要使用多個並行代理
  3. 或者只是讓你的代碼更干凈:)

這是 groovy 中的一個人為示例:

// proxy configuration read from file resource under "proxyFileName"
String proxyFileName = "proxy.txt"
String proxyPort = "1234"
String url = "http://www.promised.land"
File testProxyFile = new File(proxyFileName)
URLConnection connection

if (!testProxyFile.exists()) {

    logger.debug "proxyFileName doesn't exist.  Bypassing connection via proxy."
    connection = url.toURL().openConnection()

} else {
    String proxyAddress = testProxyFile.text
    connection = url.toURL().openConnection(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyAddress, proxyPort)))
}

try {
    connection.connect()
}
catch (Exception e) {
    logger.error e.printStackTrace()
}

完整參考: http ://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html

最近我發現了允許 JVM 使用瀏覽器代理設置的方法。 您需要做的是將${java.home}/lib/deploy.jar添加到您的項目並像下面這樣初始化庫:

import com.sun.deploy.net.proxy.DeployProxySelector;
import com.sun.deploy.services.PlatformType;
import com.sun.deploy.services.ServiceManager;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class ExtendedProxyManager {

    private static final Log logger = LogFactory.getLog(ExtendedProxyManager.class);

    /**
     * After calling this method, proxy settings can be magically retrieved from default browser settings.
     */
    public static boolean init() {
        logger.debug("Init started");

        // Initialization code was taken from com.sun.deploy.ClientContainer:
        ServiceManager
                .setService(System.getProperty("os.name").toLowerCase().indexOf("windows") != -1 ? PlatformType.STANDALONE_TIGER_WIN32
                        : PlatformType.STANDALONE_TIGER_UNIX);

        try {
            // This will call ProxySelector.setDefault():
            DeployProxySelector.reset();
        } catch (Throwable throwable) {
            logger.error("Unable to initialize extended dynamic browser proxy settings support.", throwable);

            return false;
        }

        return true;
    }
}

之后代理設置可通過java.net.ProxySelector用於 Java API。

這種方法的唯一問題是您需要在 bootclasspath 中使用deploy.jar啟動 JVM,例如java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar 如果有人知道如何克服這個限制,請告訴我。

這對我行得通:

public void setHttpProxy(boolean isNeedProxy) {
    if (isNeedProxy) {
        System.setProperty("http.proxyHost", getProxyHost());
        System.setProperty("http.proxyPort", getProxyPort());
    } else {
        System.clearProperty("http.proxyHost");
        System.clearProperty("http.proxyPort");
    }
}

P/S:我基於 GHad 的回答。

正如其他答案中指出的那樣,如果您需要使用經過身份驗證的代理,則沒有可靠的方法來純粹使用命令行變量來做到這一點 - 如果您使用的是其他人的應用程序並且不想弄亂源代碼。

Will IversonUsing HttpProxy to connect to a host with preemtive authentication中提出了有用的建議,以使用 Proxifier 等代理管理工具(Mac OS X 和 Windows 為http://www.proxifier.com/ )來處理這個問題。

例如,使用 Proxifier,您可以將其設置為僅攔截要通過其(經過身份驗證的)代理管理和重定向的 java 命令。 不過,在這種情況下,您需要將 proxyHost 和 proxyPort 值設置為空白,例如將-Dhttp.proxyHost= -Dhttp.proxyPort=傳遞給您的 java 命令。

這是一個對我有用的完整示例 - 請注意,對於 HTTPS,有單獨的屬性(根據https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html )。

下面的代碼向https://api.myip.com API 發送請求並打印響應。

public static void main(String[] args) throws IOException {
    System.setProperty("java.net.useSystemProxies", "true");
    final String proxyUser = "lum-customer-c_f95783f5-zone-datacenter-ip-92.240.207.56";
    final String proxyPass = "s3mgwrx2b628";
    final String host = "zproxy.lum-superproxy.io";
    final Integer port = 22225;

    // http
    System.setProperty("http.proxyHost",host);
    System.setProperty("http.proxyPort", String.valueOf(port));
    System.setProperty("http.proxyUser", proxyUser);
    System.setProperty("http.proxyPassword", proxyPass);

    // https
    System.setProperty("https.proxyHost",host);
    System.setProperty("https.proxyPort", String.valueOf(port));
    System.setProperty("https.proxyUser", proxyUser);
    System.setProperty("https.proxyPassword", proxyPass);

    System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
    System.setProperty("jdk.https.auth.tunneling.disabledSchemes", "");

    Authenticator.setDefault(new Authenticator() {
                @Override
                public PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(proxyUser, proxyPass.toCharArray());
                }
        }
    );

    // create and send a https request to myip.com API
    URL url = new URL("https://api.myip.com");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setRequestMethod("GET");
    int status = connection.getResponseCode();
    
    // read the response
    BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    String responseLine;
    StringBuffer responseContent = new StringBuffer();
    while ((responseLine = in.readLine()) != null) 
        responseContent.append(responseLine);
    
    in.close();
    connection.disconnect();
    
    // print the response
    System.out.println(status);
    System.out.println(responseContent);
}

如果您在獨立的 JVM 中,您可以使用 http.proxy* JVM 變量,但您不應該修改它們的啟動腳本和/或在您的應用程序服務器中執行此操作(可能除了 jboss 或 tomcat)。 相反,您應該使用 JAVA 代理 API(而不是 System.setProperty)或使用供應商自己的配置選項。 WebSphere 和 WebLogic 都有非常明確的方法來設置比 J2SE 強大得多的代理。 此外,對於 WebSphere 和 WebLogic,您可能會通過覆蓋啟動腳本(特別是服務器的互操作進程,因為您可能會告訴他們也使用您的代理...)來破壞您的應用程序服務器。

我認為配置WINHTTP也可以。

包括 Windows 更新在內的許多程序都存在代理問題。 通過設置WINHTTP總會解決這類問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM