Wie stelle ich den Proxy ein, der von der JVM verwendet werden soll?

308

Oft muss eine Java-App eine Verbindung zum Internet herstellen. Das häufigste Beispiel tritt auf, wenn eine XML-Datei gelesen wird und das Schema heruntergeladen werden muss.

Ich bin hinter einem Proxyserver. Wie kann ich meine JVM so einstellen, dass sie den Proxy verwendet?

Leonel
quelle
Die Oracle-Dokumentation dazu scheint ziemlich veraltet zu sein (obwohl sie wahrscheinlich immer noch gültig ist). Hier ist etwas Moderneres aus dem Frühling: docs.spring.io/spring-integration/reference/html/…
nobar

Antworten:

350

Aus der Java-Dokumentation ( nicht der Javadoc-API):

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

Setzen Sie die JVM-Flags http.proxyHostund http.proxyPortstarten Sie Ihre JVM in der Befehlszeile. Dies erfolgt normalerweise in einem Shell-Skript (unter Unix) oder einer Bat-Datei (unter Windows). Hier ist das Beispiel mit dem Unix-Shell-Skript:

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

Bei Verwendung von Containern wie JBoss oder WebLogic besteht meine Lösung darin, die vom Hersteller bereitgestellten Startskripts zu bearbeiten.

Viele Entwickler sind mit der Java-API (Javadocs) vertraut, aber der Rest der Dokumentation wird oft übersehen. Es enthält viele interessante Informationen: http://download.oracle.com/javase/6/docs/technotes/guides/


Update: Wenn Sie keinen Proxy zum Auflösen einiger lokaler / Intranet-Hosts verwenden möchten, lesen Sie den Kommentar von @Tomalak:

Vergessen Sie auch nicht die Eigenschaft http.nonProxyHosts!

-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com‌​|etc"
Leonel
quelle
109
+1. Vergessen Sie auch nicht die http.nonProxyHostsEigenschaft! (Verwendung wie folgt aus : -Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc")
Tomalak
3
Hallo Leute, wie kannst du den Benutzernamen und das Passwort auch hier einfügen? Danke
Joeblackdev
8
@ Joeblackdev Blick auf http.proxyUser und http.proxyPassword
aasukisuki
4
@aasukisuki http.proxyUserund http.proxyPasswordsind keine Java-Systemeigenschaften. Sie sind für den Apache HTTP-Client.
Marquis von Lorne
24
Auch vergessen Sie nicht zu konfigurieren https.proxyHostund https.proxyPortfür HTTPs.
C-Otto
103

So verwenden Sie das System-Proxy-Setup:

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

Oder programmatisch:

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

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

gr5
quelle
Awesome Einstellung JVM Argument funktioniert für mich wie Charme .. Danke
Nanosoft
Ich habe diesen Code verwendet, um den Proxy durch den Wert "false" auf meinem SSLSocket zu deaktivieren. Vielen Dank.
Fer
1
Vielleicht liegt es daran, dass mein Proxy eine Authentifizierung erfordert, aber das hat bei mir nicht funktioniert. Ich wünschte es wäre so.
Simon Forsberg
3
Dies funktioniert nicht mit PAC-Dateien (Proxy Auto-Config), siehe stackoverflow.com/questions/10324996/…
Michael_S
80

So legen Sie programmgesteuert einen HTTP / HTTPS- und / oder SOCKS-Proxy fest:

...

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;
    }
}

...

Denken Sie daran, dass HTTP-Proxys und SOCKS-Proxys auf verschiedenen Ebenen im Netzwerkstapel ausgeführt werden, sodass Sie den einen oder den anderen oder beide verwenden können.

Chris Carruthers
quelle
4
Wenn "java.net.socks.username / password" festgelegt ist, warum auch einen Authenticator festlegen?
Marquis von Lorne
1
Warum wird "con.setRequest ..." nicht erkannt? Welche Bibliotheken werden dafür benötigt?
Randnum
1
+1 für die Socken-Proxy-Option, da manchmal http-Proxy mein Problem nicht lösen kann
Manuzhang
1
In meinen Tests funktioniert es, wenn Sie nur den Standardauthentifizierer festlegen - keine Notwendigkeit, die Authentifizierungseigenschaften festzulegen
Drew Stephens
1
Funktioniert nicht, wenn Sie nur die Systemeigenschaften verwenden. Denkt, dass die Eigenschaften von java.net.socks. (Benutzername | Passwort) nichts bewirken.
Drew Stephens
46

Sie können diese Flags programmgesteuert folgendermaßen setzen:

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

Geben Sie einfach die richtigen Werte aus den Methoden zurück needsProxy(), getProxyHost()und getProxyPort()Sie können dieses Code-Snippet jederzeit aufrufen.

GHad
quelle
34
"proxySet" macht nichts. Beweis: Setzen Sie es auf "false". Ungeachtet verschiedener Bücher und Online-Referenzen gibt es im JDK keine solche Eigenschaft und es gab sie auch nie. Es kam von der längst nicht mehr existierenden HotJavaBean, einem gekapselten Browser, der ungefähr 1998 starb.
Marquis of Lorne
2
Sind die Eigenschaftsnamen wirklich ohne http / https?
Betlista
18
Dies ist in dreierlei Hinsicht falsch: 1: Wie bereits erwähnt, gibt es kein "proxySet" -Element. 2: "proxyHost" und "proxyPort" müssen "http.proxyHost" und "http.proxyPort" (oder das Äquivalent "https") sein. 3: System.getProperties (). Put (X, Y) ist nicht dasselbe wie System.setProperty (X, Y). Davon abgesehen aber - tolle Antwort.
Rob Cranfill
1
@RobCranfill 1: "proxySet" war früher ein nicht standardmäßiges Flag, das von einem alten JDK benötigt wurde, aber nicht mehr benötigt wird. 2: "proxyHost" und "proxyPort" funktionieren, das "http". Das Präfix beschränkt sie nur auf das HTTP-Protokoll (ähnlich wie bei "https"). 3: Hier haben Sie Recht.
Werkzeugschmied
24

JVM verwendet den Proxy, um HTTP-Aufrufe zu tätigen

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

Dies kann einen Benutzereinstellungs-Proxy verwenden

System.setProperty("java.net.useSystemProxies", "true");
Sarath
quelle
Verwenden Sie System.setPropertyanstelle vonSystem.getProperties().put(...)
Simon Forsberg
12

Sie können einige Eigenschaften des Proxyservers als JVM-Parameter festlegen

-Dhttp.proxyPort = 8080, proxyHost usw.

Wenn Sie jedoch einen authentifizierenden Proxy durchlaufen müssen, benötigen Sie einen Authentifikator wie das folgende:

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;
    }
}

Beispiel.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

    }
}

Basierend auf dieser Antwort: http://mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/200208.mbox/%3C494FD350388AD511A9DD00025530F33102F1DC2C@MMSX006%3E

Alex. S.
quelle
Das funktioniert nicht. Wenn Sie noch nicht authentifiziert sind, erhält die erste Zeile in der Hauptfunktion eine Reihe von Nullwerten und der Code stoppt. Dies hilft niemandem, sein JVM zu authentifizieren, damit er URL-Aufrufe über einen Proxy tätigen kann.
Randnum
12

Kombinieren Sie die Antworten von Sorter und Javabrett / Leonel:

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

Setzen Sie die java.net.useSystemProxiesEigenschaft auf true. Sie können dies beispielsweise über die Umgebungsvariable JAVA_TOOL_OPTIONS festlegen . In Ubuntu können Sie beispielsweise die folgende Zeile hinzufügen .bashrc:

export JAVA_TOOL_OPTIONS + = "-Djava.net.useSystemProxies = true"

Mihai Capotă
quelle
9

Im Folgenden wird gezeigt, wie in Java ein Proxy mit Proxy-Benutzer und Proxy-Kennwort über die Befehlszeile festgelegt wird. Dies ist ein sehr häufiger Fall. Sie sollten in der Regel in erster Linie keine Passwörter und Hosts im Code speichern.

Das Übergeben der Systemeigenschaften in der Befehlszeile mit -D und das Festlegen im Code mit System.setProperty ("Name", "Wert") ist äquivalent.

Beachten Sie dies jedoch

Beispiel, das funktioniert:

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

Aber folgendes funktioniert nicht :

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

Der einzige Unterschied ist die Position der Systemeigenschaften! (vor und nach dem Unterricht)

Wenn das Passwort Sonderzeichen enthält, können Sie es wie im obigen Beispiel in Anführungszeichen "@ MyPass123%" setzen.

Wenn Sie einen HTTPS - Dienst zugreifen, müssen Sie verwenden https.proxyHost, https.proxyPortusw.

Wenn Sie einen HTTP - Dienst zugreifen, müssen Sie verwenden http.proxyHost, http.proxyPortusw.

Andreas Panagiotidis
quelle
5
ProxyUser und proxyPassword sind keine Java-Systemeigenschaften, sondern Apache-HTTP-Client-Eigenschaften, sodass dies nicht in allen Fällen funktioniert.
THelper
8

Lesen einer XML-Datei und muss das Schema herunterladen

Wenn Sie darauf zählen, Schemas oder DTDs über das Internet abzurufen, erstellen Sie eine langsame, gesprächige und fragile Anwendung. Was passiert, wenn der Remote-Server, auf dem sich die Datei befindet, geplante oder ungeplante Ausfallzeiten benötigt? Ihre App bricht ab. Ist das in Ordnung?

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

URLs für Schemas und dergleichen werden am besten als eindeutige Bezeichner angesehen. Nicht als Anforderung, tatsächlich remote auf diese Datei zuzugreifen. Führen Sie eine Google-Suche im "XML-Katalog" durch. Mit einem XML-Katalog können Sie solche Ressourcen lokal hosten und so Langsamkeit, Geschwätz und Fragilität beheben.

Es ist im Grunde eine permanent zwischengespeicherte Kopie des Remote-Inhalts. Und das ist in Ordnung, da sich der Remote-Inhalt niemals ändern wird. Wenn es jemals ein Update gibt, wird es unter einer anderen URL sein. Das eigentliche Abrufen der Ressource über das Internet besonders dumm zu machen.

John M.
quelle
7

Ich bin auch hinter der Firewall, das hat bei mir funktioniert !!

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();
Pallavi
quelle
5

Wenn Sie "Socks Proxy" möchten, informieren Sie die VM-Argumente "socksProxyHost" und "socksProxyPort".

z.B

java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main
Marcelo C.
quelle
4

Fügen Sie dies hinzu, bevor Sie eine Verbindung zu einer URL hinter einem Proxy herstellen.

System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");
System.getProperties().put("http.proxyUser", "someUserName");
System.getProperties().put("http.proxyPassword", "somePassword");
Sorter
quelle
4
http.proxyUserund http.proxyPasswordsind keine Java-Systemeigenschaften. Sie sind für den Apache HTTP-Client.
Marquis von Lorne
Verwenden Sie System.setPropertyanstelle vonSystem.getProperties().put(...)
Simon Forsberg
4

Dies ist ein kleines Update, aber seit Java 7 können Proxy-Verbindungen jetzt programmgesteuert und nicht mehr über Systemeigenschaften erstellt werden. Dies kann nützlich sein, wenn:

  1. Der Proxy muss während der Laufzeit des Programms dynamisch gedreht werden
  2. Es müssen mehrere parallele Proxys verwendet werden
  3. Oder machen Sie einfach Ihren Code sauberer :)

Hier ist ein erfundenes Beispiel in 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()
}

Vollständige Referenz: http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html

Philip M.
quelle
2
Dies ist seit Java 1.5, nicht 1.7.
Marquis von Lorne
3

Kürzlich habe ich herausgefunden, wie JVM Browser-Proxy-Einstellungen verwenden kann. Was Sie tun müssen, ist, ${java.home}/lib/deploy.jarIhrem Projekt etwas hinzuzufügen und die Bibliothek wie folgt zu initiieren:

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;
    }
}

Anschließend stehen die Proxy-Einstellungen der Java API über zur Verfügung java.net.ProxySelector.

Das einzige Problem bei diesem Ansatz ist, dass Sie JVM mit deploy.jarin bootclasspath starten müssen, z java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar. Wenn jemand weiß, wie er diese Einschränkung überwinden kann, lassen Sie es mich wissen.

dma_k
quelle
1
Ich wünschte, ich könnte dies mehrmals positiv bewerten, es ist die einzige Lösung, die für mich funktioniert hat. Danke! Ich musste das Apache Commons-Protokollierungsglas von hier herunterladen : commons.apache.org/proper/commons-logging/download_logging.cgi Mein Code in Main (): System.setProperty ("java.net.useSystemProxies", "true") ;; System.out.println ("Proxys erkennen"); ExtendedProxyManager.init ();
Boris
Was hätte der xbootclasspathHinweis auf deploy.jar für die Wirkung? Könnte ich dieses Glas nicht auf meinen normalen Klassenpfad übertragen (wenn es ohne Webstart ausgeführt wird)?
Houtman
1
in JDK 9 schlägt es fehl :( Exception in thread "main" java.lang.IllegalAccessError: class ...) cannot access class com.sun.deploy.net.proxy.DeployProxySelector (in module jdk.deploy) because module jdk.deploy does not export com.sun.deploy.net.proxy
Houtman
2

Das ist für mich in Ordnung:

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: Ich stütze mich auf GHads Antwort.

Viet Tran
quelle
Diese Antwort enthält nichts, was in den anderen Antworten noch nicht gesagt wurde.
Simon Forsberg
1

Wie in anderen Antworten ausgeführt, gibt es keine zuverlässige Möglichkeit, authentifizierte Proxys zu verwenden, wenn Sie authentifizierte Proxys verwenden. Dies ist ärgerlich, wenn Sie die Anwendung eines anderen Benutzers verwenden und sich nicht mit dem herumspielen möchten Quellcode.

Will Iverson macht den hilfreichen Vorschlag unter Verwenden von HttpProxy, um eine Verbindung zu einem Host mit vorläufiger Authentifizierung herzustellen , um ein Proxy-Verwaltungstool wie Proxifier ( http://www.proxifier.com/ für Mac OS X und Windows) zu verwenden, um dies zu handhaben.

Mit Proxifier können Sie beispielsweise festlegen, dass nur Java-Befehle abgefangen werden, die über den (authentifizierten) Proxy verwaltet und umgeleitet werden sollen. In diesem Fall sollten Sie jedoch die Werte für proxyHost und proxyPort auf leer setzen, z. B. -Dhttp.proxyHost= -Dhttp.proxyPort=an Ihre Java-Befehle übergeben.

patdevelop
quelle
-1

Sie können die http.proxy * JVM-Variablen verwenden, wenn Sie sich in einer eigenständigen JVM befinden, aber Sie sollten deren Startskripte NICHT ändern und / oder dies auf Ihrem Anwendungsserver tun (außer vielleicht jboss oder tomcat). Verwenden Sie stattdessen die JAVA-Proxy-API (nicht System.setProperty) oder die Konfigurationsoptionen des Herstellers. Sowohl WebSphere als auch WebLogic verfügen über sehr definierte Methoden zum Einrichten der Proxys, die weitaus leistungsfähiger sind als die von J2SE. Darüber hinaus werden Sie für WebSphere und WebLogic Ihren Anwendungsserver wahrscheinlich auf geringfügige Weise beschädigen, indem Sie die Startskripte überschreiben (insbesondere die Interop-Prozesse des Servers, da Sie ihn möglicherweise anweisen, auch Ihren Proxy zu verwenden ...).


quelle
-5

Ich denke, die Konfiguration von WINHTTP wird auch funktionieren.

Viele Programme, einschließlich Windows-Updates, haben Probleme mit dem Proxy. Durch das Einrichten von WINHTTP werden diese Probleme immer behoben

Nylas
quelle