Jak ustawić serwer proxy do używania przez JVM

307

Wiele razy aplikacja Java musi łączyć się z Internetem. Najczęstszy przykład ma miejsce, gdy czyta plik XML i musi pobrać jego schemat.

Jestem za serwerem proxy. Jak mogę ustawić moją JVM do używania proxy?

Leonel
źródło
Dokumentacja Oracle wokół tego wydaje się dość przestarzała (choć nadal prawdopodobnie ważna). Oto coś bardziej nowoczesnego od wiosny: docs.spring.io/spring-integration/reference/html/…
nobar

Odpowiedzi:

350

Z dokumentacji Java ( nie API javadoc):

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

Ustaw flagi JVM http.proxyHosti http.proxyPortpodczas uruchamiania JVM w wierszu polecenia. Zwykle odbywa się to w skrypcie powłoki (w systemie Unix) lub w pliku bat (w systemie Windows). Oto przykład ze skryptem powłoki Uniksa:

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

Podczas korzystania z kontenerów takich jak JBoss lub WebLogic, moim rozwiązaniem jest edycja skryptów startowych dostarczonych przez dostawcę.

Wielu programistów zna Java API (javadocs), ale wiele razy reszta dokumentacji jest pomijana. Zawiera wiele interesujących informacji: http://download.oracle.com/javase/6/docs/technotes/guides/


Aktualizacja: jeśli nie chcesz używać proxy do rozwiązania niektórych hostów lokalnych / intranetowych, sprawdź komentarz z @Tomalak:

Nie zapomnij również o właściwości http.nonProxyHosts!

-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com‌​|etc"
Leonel
źródło
109
+1. Nie zapomnij także o http.nonProxyHostsnieruchomości! (zastosowanie tak: -Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc")
Tomalak
3
Cześć chłopaki, jak możecie dołączyć do tego nazwę użytkownika i hasło? Dzięki
Joeblackdev
8
@Jeblebldev spójrz na http.proxyUser i http.proxyPassword
aasukisuki
4
@aasukisuki http.proxyUseri http.proxyPasswordnie są właściwościami systemu Java. Są dla klienta HTTP Apache.
Markiz Lorne
24
Nie zapomnij również skonfigurować https.proxyHosti https.proxyPortdla HTTPs.
C-Otto
102

Aby użyć systemowego ustawienia proxy:

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

Lub programowo:

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

Źródło: http://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html

gr5
źródło
Niesamowite ustawienie argumentów Jvm działa dla mnie jak urok .. Dzięki
nanosoft
Użyłem tego kodu, aby wyłączyć proxy przez wartość „false” na moim SSLSocket. Dzięki.
Fer
1
Być może dzieje się tak, ponieważ mój serwer proxy wymaga uwierzytelnienia, ale to nie działało dla mnie. Chciałbym, żeby tak było.
Simon Forsberg
3
Nie działa to z plikami automatycznej
konfiguracji
80

Aby programowo ustawić serwer proxy HTTP / HTTPS i / lub 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;
    }
}

...

Pamiętaj, że proxy HTTP i proxy SOCKS działają na różnych poziomach w stosie sieciowym, więc możesz użyć jednego lub drugiego lub obu.

Chris Carruthers
źródło
4
Jeśli ustawione są „java.net.socks.username / password”, to po co ustawiać także Authenticator?
Markiz Lorne
1
dlaczego nie jest „con.setRequest ...” oszustwo nie jest rozpoznawane. Jakie biblioteki są do tego potrzebne.
Randnum
1
+1 za opcję proxy skarpet, ponieważ czasami serwer proxy HTTP nie może rozwiązać mojego problemu
manuzhang
1
W moich testach działa, jeśli ustawisz tylko domyślny Authenticator - nie musisz ustawiać właściwości uwierzytelniania
Drew Stephens,
1
Nie działa, jeśli masz tylko właściwości systemowe. Methinks java.net.socks. (Nazwa użytkownika | hasło) nic nie robi.
Drew Stephens
46

Możesz ustawić te flagi programowo w ten sposób:

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

Wystarczy zwrócić odpowiednie wartości z metod needsProxy(), getProxyHost()a getProxyPort()można nazwać ten fragment kodu, kiedy tylko chcesz.

GHad
źródło
34
„proxySet” nic nie robi. Dowód: ustaw na „fałsz”. Nie ma i nigdy nie było takiej właściwości w JDK, pomimo różnych książek i referencji online. Pochodzi z od dawna nieistniejącego HotJavaBean, zamkniętej przeglądarki, zmarł śmiercią około 1998 roku.
Markiz Lorne
2
Naprawdę są nazwy właściwości bez http / https?
Betlista
18
Jest to błędne z trzech powodów: 1: jak wspomniano, nie ma elementu „proxySet”; 2: „proxyHost” i „proxyPort” muszą być „http.proxyHost” i „http.proxyPort” (lub odpowiednikiem „https”); 3: System.getProperty (). Put (X, Y) to nie to samo co System.setProperty (X, Y). Ale poza tym - świetna odpowiedź.
Rob Cranfill,
1
@RobCranfill 1: „proxySet” był niestandardową flagą, która była potrzebna przez stary JDK, ale nie jest już konieczna; 2: działają „proxyHost” i „proxyPort”, „http”. prefiks ogranicza je tylko do protokołu HTTP (podobnie jak w przypadku „https.”), 3: masz rację.
toolforger
24

JVM używa proxy do wykonywania połączeń HTTP

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

Może to korzystać z serwera proxy ustawień użytkownika

System.setProperty("java.net.useSystemProxies", "true");
sarath
źródło
Użyj System.setPropertyzamiastSystem.getProperties().put(...)
Simon Forsberg
12

Możesz ustawić niektóre właściwości dotyczące serwera proxy jako parametry jvm

-Dhttp.proxyPort = 8080, proxyHost itp.

ale jeśli potrzebujesz przekazać przez proxy uwierzytelniające, potrzebujesz uwierzytelnienia takiego jak ten przykład:

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

    }
}

Na podstawie tej odpowiedzi: http://mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/200208.mbox/%3C494FD350388AD511A9DD00025530F33102F1DC2C@MMSX006%3E

Alex. S.
źródło
to nie działa. jeśli nie jesteś jeszcze uwierzytelniony, pierwszy wiersz funkcji głównej otrzymuje wiązkę wartości zerowych i kod zatrzymuje się. To nie pomaga komuś uwierzytelnić swojego pliku Jvm, aby mógł wykonywać połączenia URL przez serwer proxy.
Randnum,
12

Łączenie odpowiedzi Sortera i javabretta / Leonela:

java -Dhttp.proxyHost=10.10.10.10 -Dhttp.proxyPort=8080 -Dhttp.proxyUser=username -Dhttp.proxyPassword=password -jar myJar.jar
Bamboomy
źródło
10

Ustaw java.net.useSystemProxieswłaściwość na true. Możesz to ustawić na przykład za pomocą zmiennej środowiskowej JAVA_TOOL_OPTIONS . W Ubuntu możesz na przykład dodać następujący wiersz .bashrc:

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

Mihai Capotă
źródło
9

Poniżej pokazano, jak ustawić w Javie proxy z użytkownikiem proxy i hasłem proxy z wiersza poleceń, co jest bardzo częstym przypadkiem. Zasadniczo nie należy zapisywać haseł i hostów w kodzie.

Przekazywanie właściwości systemu w wierszu poleceń za pomocą -D i ustawianie ich w kodzie za pomocą System.setProperty („nazwa”, „wartość”) jest równoważne.

Ale zauważ to

Przykład, który działa:

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

Ale następujące działania nie działają :

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

Jedyną różnicą jest położenie właściwości systemu! (przed i po zajęciach)

Jeśli masz hasło specjalne, możesz wpisać je w cudzysłowie „@ MyPass123%”, jak w powyższym przykładzie.

Jeśli masz dostęp do usługi HTTPS, trzeba użyć https.proxyHost, https.proxyPortetc.

Jeśli masz dostęp do usługi HTTP, trzeba użyć http.proxyHost, http.proxyPortetc.

Andreas Panagiotidis
źródło
5
ProxyUser i proxyPassword nie są właściwościami systemu Java, ale właściwościami klienta Apache HTTP, więc nie we wszystkich przypadkach.
THelper
8

odczytuje plik XML i musi pobrać jego schemat

Jeśli liczysz na pobieranie schematów lub DTD przez Internet, budujesz powolną, gadatliwą, delikatną aplikację. Co się stanie, gdy zdalny serwer hostujący plik zajmie planowane lub nieplanowane przestoje? Twoja aplikacja się psuje. Czy to w porządku?

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

Adresy URL schematów i tym podobne najlepiej traktować jako unikalne identyfikatory. Nie jako żądania zdalnego dostępu do tego pliku. Wyszukaj w Google „Katalog XML”. Katalog XML pozwala hostować takie zasoby lokalnie, co rozwiązuje powolność, spryt i kruchość.

Jest to zasadniczo trwale buforowana kopia zdalnej zawartości. I to jest w porządku, ponieważ zdalna zawartość nigdy się nie zmieni. Jeśli kiedykolwiek pojawi się aktualizacja, będzie ona dostępna pod innym adresem URL. Sprawienie, by faktyczne pobieranie zasobów przez Internet było szczególnie głupie.

John M.
źródło
7

Jestem również za firewallem, to zadziałało dla mnie !!

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
źródło
5

Jeśli chcesz użyć „Socks Proxy”, poinformuj o argumentach maszyny wirtualnej „socksProxyHost” i „socksProxyPort”.

na przykład

java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main
Marcelo C.
źródło
4

Dodaj to, zanim połączysz się z adresem URL za serwerem proxy.

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
źródło
4
http.proxyUseri http.proxyPasswordnie są właściwościami systemu Java. Są dla klienta HTTP Apache.
Markiz Lorne
Użyj System.setPropertyzamiastSystem.getProperties().put(...)
Simon Forsberg
4

Jest to niewielka aktualizacja, ale od wersji Java 7 połączenia proxy można teraz tworzyć programowo, a nie za pomocą właściwości systemu. Może to być przydatne, jeśli:

  1. Serwer proxy musi być dynamicznie obracany podczas działania programu
  2. Należy użyć wielu równoległych serwerów proxy
  3. Lub po prostu uczyń swój kod czystszym :)

Oto wymyślony przykład w 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()
}

Pełny opis: http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html

Philip M.
źródło
2
Wynika to z wersji Java 1.5, a nie 1.7.
Markiz Lorne
3

Ostatnio odkryłem sposób, w jaki JVM może korzystać z ustawień proxy przeglądarki. Musisz dodać ${java.home}/lib/deploy.jardo projektu i zainicjować bibliotekę w następujący sposób:

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

Następnie ustawienia proxy są dostępne dla Java API poprzez java.net.ProxySelector.

Jedynym problemem związanym z tym podejściem jest to, że musisz uruchomić JVM deploy.jarw ścieżce rozruchowej, np java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar. Jeśli ktoś wie, jak pokonać to ograniczenie, daj mi znać.

dma_k
źródło
1
Chciałbym móc to wielokrotnie głosować, to jedyne rozwiązanie, które dla mnie zadziałało; Dziękuję Ci! Musiałem pobrać słoik rejestrujący apache commons stąd: commons.apache.org/proper/commons-logging/download_logging.cgi Mój kod w Main (): System.setProperty („java.net.useSystemProxies”, „true”) ; System.out.println („wykrywanie serwerów proxy”); ExtendedProxyManager.init ();
Boris
Co xbootclasspathwskazywałoby na wdrożenie deploy.jar, czy nie mogę przenieść tego słoika na moją normalną ścieżkę klasy (podczas uruchamiania bez uruchamiania sieci)?
Houtman
1
w JDK 9 nie udaje się :( 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

To działa dla mnie:

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: Opieram się na odpowiedzi GHada.

Viet Tran
źródło
Ta odpowiedź nie zawiera niczego, co nie zostało jeszcze powiedziane w innych odpowiedziach.
Simon Forsberg
1

Jak wskazano w innych odpowiedziach, jeśli chcesz używać uwierzytelnionych serwerów proxy, nie ma niezawodnego sposobu, aby to zrobić przy użyciu zmiennych wiersza polecenia - co jest denerwujące, jeśli używasz aplikacji innej osoby i nie chcesz zadzierać z kod źródłowy.

Czy Iverson przedstawia przydatne sugestie na temat korzystania z HttpProxy w celu połączenia się z hostem za pomocą wstępnego uwierzytelnienia w celu skorzystania z narzędzia do zarządzania proxy, takiego jak Proxifier ( http://www.proxifier.com/ dla Mac OS X i Windows).

Na przykład w Proxifier możesz ustawić, aby przechwytywał tylko polecenia Java, którymi można zarządzać i przekierowywać przez (uwierzytelnione) proxy. Będziesz jednak chciał ustawić wartości proxyHost i proxyPort na puste w tym przypadku, np. Przekaż -Dhttp.proxyHost= -Dhttp.proxyPort=komendę java.

patdevelop
źródło
-1

Możesz użyć zmiennych http.proxy * JVM, jeśli jesteś w autonomicznej JVM, ale NIE POWINIENEŚ modyfikować ich skryptów startowych i / lub robić tego na serwerze aplikacji (z wyjątkiem może jboss lub tomcat). Zamiast tego należy użyć interfejsu API serwera proxy JAVA (nie System.setProperty) lub własnych opcji konfiguracji dostawcy. Zarówno WebSphere, jak i WebLogic mają bardzo zdefiniowane sposoby konfigurowania serwerów proxy, które są znacznie potężniejsze niż J2SE. Ponadto w przypadku WebSphere i WebLogic prawdopodobnie zepsujesz serwer aplikacji w niewielki sposób, zastępując skrypty startowe (w szczególności procesy międzyoperacyjne serwera, ponieważ możesz im również powiedzieć, aby korzystali z twojego serwera proxy ...).


źródło
-5

Myślę, że konfiguracja WINHTTP również będzie działać.

Wiele programów, w tym aktualizacje systemu Windows, ma problemy z serwerem proxy. Skonfigurowanie WINHTTP zawsze rozwiąże tego rodzaju problemy

nylas
źródło