Come posso impostare il proxy per essere utilizzato dalla JVM


308

Molte volte, un'app Java deve connettersi a Internet. L'esempio più comune si verifica quando sta leggendo un file XML e deve scaricare il suo schema.

Sono dietro un server proxy. Come posso impostare la mia JVM per usare il proxy?


La documentazione Oracle su questo sembra piuttosto stantia (anche se probabilmente ancora valida). Ecco qualcosa di più moderno della primavera: docs.spring.io/spring-integration/reference/html/…
nobar

Risposte:


350

Dalla documentazione Java ( non dall'API javadoc):

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

Impostare i flag JVM http.proxyHoste http.proxyPortquando si avvia JVM sulla riga di comando. Questo di solito viene fatto in uno script di shell (in Unix) o in un file bat (in Windows). Ecco l'esempio con lo script della shell Unix:

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

Quando si utilizzano contenitori come JBoss o WebLogic, la mia soluzione è quella di modificare gli script di avvio forniti dal fornitore.

Molti sviluppatori hanno familiarità con l'API Java (javadocs), ma molte volte il resto della documentazione viene trascurato. Contiene molte informazioni interessanti: http://download.oracle.com/javase/6/docs/technotes/guides/


Aggiornamento: se non si desidera utilizzare il proxy per risolvere alcuni host locali / intranet, consultare il commento da @Tomalak:

Inoltre, non dimenticare la proprietà http.nonProxyHosts!

-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com‌​|etc"

109
+1. Inoltre, non dimenticare la http.nonProxyHostsproprietà! (uso in questo modo: -Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc")
Tomalak

3
Ciao ragazzi, come potete includere anche nome utente e password in questo? Grazie
Joeblackdev l'

8
@Joeblackdev guarda http.proxyUser e http.proxyPassword
aasukisuki

4
@aasukisuki http.proxyUsere http.proxyPasswordnon sono proprietà di sistema Java. Sono per il client HTTP Apache.
Marchese di Lorne,

24
Inoltre, non dimenticare di configurare https.proxyHoste https.proxyPortper HTTPs.
C-Otto,

103

Per utilizzare la configurazione proxy del sistema:

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

O programmaticamente:

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

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


Fantastica ambientazione jvm arguement funziona per me come per il fascino .. Grazie
nanosoft,

Ho usato questo codice per disabilitare il proxy dal valore "false" sul mio SSLSocket. Grazie.
Fer

1
Forse è perché il mio proxy richiede l'autenticazione, ma questo non ha funzionato per me. Vorrei che fosse così.
Simon Forsberg,

3
Questo non funziona con i file Proxy Auto-Config (PAC), vedi stackoverflow.com/questions/10324996/…
Michael_S

80

Per impostare un proxy HTTP / HTTPS e / o SOCKS a livello di codice:

...

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

...

Ricorda che i proxy HTTP e i proxy SOCKS operano a diversi livelli nello stack di rete, quindi puoi utilizzare l'uno o l'altro o entrambi.


4
Se è impostato "java.net.socks.username / password", perché anche impostare un Authenticator?
Marchese di Lorne,

1
perché non è "con.setRequest ..." il con non è riconosciuto. Quali librerie sono necessarie per questo.
Randnum,

1
+1 per l'opzione proxy socks in quanto a volte il proxy http non può risolvere il mio problema
manuzhang

1
Nel mio test, funziona solo se hai impostato l'Autenticatore predefinito, non è necessario impostare le proprietà di autenticazione
Drew Stephens,

1
Non funziona se hai solo le proprietà di sistema. Pensa che le proprietà java.net.socks (nome utente | password) non facciano nulla.
Stephens il

46

È possibile impostare tali flag a livello di codice in questo modo:

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

Basta restituire i giusti valori dai metodi needsProxy(), getProxyHost()e getProxyPort()ed è possibile chiamare questo frammento di codice ogni volta che vuoi.


34
"proxySet" non fa nulla. Prova: impostalo su "false". Non esiste e non è mai stata una proprietà del genere nel JDK, nonostante vari libri e riferimenti online. Venne dal defunto HotJavaBean, un browser incapsulato, morì di morte nel 1998 circa.
Marchese di Lorne

2
I nomi delle proprietà sono davvero senza http / https?
Betlista,

18
Questo è sbagliato per tre motivi: 1: come detto, non esiste alcun elemento "proxySet"; 2: "proxyHost" e "proxyPort" devono essere "http.proxyHost" e "http.proxyPort" (o l'equivalente di "https"); 3: System.getProperties (). Put (X, Y) non è uguale a System.setProperty (X, Y). Oltre a questo, però - ottima risposta.
Rob Cranfill,


1
@RobCranfill 1: "proxySet" era un flag non standard che era necessario a un vecchio JDK ma non è più necessario; 2: "proxyHost" e "proxyPort" funzionano, il "http". il prefisso li limita al protocollo HTTP (simile a "https"), 3: qui hai ragione.
Toolforger,

24

JVM utilizza il proxy per effettuare chiamate HTTP

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

Questo può utilizzare il proxy delle impostazioni utente

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

Usa System.setPropertyinvece diSystem.getProperties().put(...)
Simon Forsberg

12

È possibile impostare alcune proprietà sul server proxy come parametri jvm

-Dhttp.proxyPort = 8080, proxyHost, ecc.

ma se è necessario passare attraverso un proxy di autenticazione, è necessario un autenticatore come questo esempio:

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

    }
}

Sulla base di questa risposta: http://mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/200208.mbox/%3C494FD350388AD511A9DD00025530F33102F1DC2C@MMSX006%3E


questo non funziona. se non si è già autenticati, la prima riga nella funzione principale ottiene un gruppo di valori null e il codice si arresta. Questo non aiuta qualcuno a autenticare il proprio jvm in modo da poter effettuare chiamate URL tramite un proxy.
Randnum,

12

Combinando le risposte di Sorter e javabrett / Leonel:

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


9

Quanto segue mostra come impostare in Java un proxy con utente proxy e password proxy dalla riga di comando, che è un caso molto comune. Non è necessario salvare password e host nel codice, come regola in primo luogo.

Passare le proprietà di sistema nella riga di comando con -D e impostarle nel codice con System.setProperty ("nome", "valore") è equivalente.

Ma nota questo

Esempio che funziona:

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

Ma quanto segue non funziona :

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

L'unica differenza è la posizione delle proprietà del sistema! (prima e dopo la lezione)

Se si dispone di caratteri speciali nella password, è possibile inserirlo tra virgolette "@ MyPass123%", come nell'esempio sopra.

Se accedi a un servizio HTTPS, devi usare https.proxyHost, https.proxyPortecc.

Se accedi a un servizio HTTP, devi usare http.proxyHost, http.proxyPortecc.


5
ProxyUser e proxyPassword non sono proprietà di sistema Java, ma proprietà client HTTP Apache quindi non funzionano in tutti i casi.
THelper

8

leggere un file XML e deve scaricare il suo schema

Se stai contando sul recupero di schemi o DTD su Internet, stai costruendo un'applicazione lenta, loquace e fragile. Cosa succede quando il server remoto che ospita il file richiede tempi di inattività pianificati o non pianificati? L'app si interrompe. È ok?

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

Gli URL per schemi e simili sono meglio pensati come identificatori univoci. Non come richieste per accedere effettivamente a quel file da remoto. Esegui una ricerca su Google nel "catalogo XML". Un catalogo XML consente di ospitare tali risorse localmente, risolvendone la lentezza, la chiacchierata e la fragilità.

È fondamentalmente una copia memorizzata nella cache permanente del contenuto remoto. E va bene, dal momento che il contenuto remoto non cambierà mai. Se c'è mai un aggiornamento, sarebbe su un URL diverso. Rendere il recupero effettivo della risorsa su Internet particolarmente sciocco.


7

Sono anche dietro il firewall, questo ha funzionato per me !!

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();

5

Se si desidera "Socks Proxy", informare gli argomenti VM "socksProxyHost" e "socksProxyPort".

per esempio

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

4

Aggiungi questo prima di connetterti a un URL dietro un 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");

4
http.proxyUsere http.proxyPasswordnon sono proprietà di sistema Java. Sono per il client HTTP Apache.
Marchese di Lorne,

Usa System.setPropertyinvece diSystem.getProperties().put(...)
Simon Forsberg

4

Questo è un aggiornamento minore, ma a partire da Java 7, ora è possibile creare connessioni proxy in modo programmatico anziché tramite le proprietà di sistema. Questo può essere utile se:

  1. Il proxy deve essere ruotato dinamicamente durante l'esecuzione del programma
  2. È necessario utilizzare più proxy paralleli
  3. O semplicemente rendi il tuo codice più pulito :)

Ecco un esempio inventato 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()
}

Riferimento completo: http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html


2
Questo è da Java 1.5, non 1.7.
Marchese di Lorne,

3

Di recente ho scoperto il modo per consentire a JVM di utilizzare le impostazioni proxy del browser. Quello che devi fare è aggiungere ${java.home}/lib/deploy.jaral tuo progetto e avviare la libreria come la seguente:

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

Successivamente le impostazioni del proxy sono disponibili per l'API Java tramite java.net.ProxySelector.

L'unico problema con questo approccio è che è necessario avviare JVM con deploy.jarbootclasspath ad es java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar. Se qualcuno sa come superare questa limitazione, fammelo sapere.


1
Vorrei poter votare più volte, è l'unica soluzione che ha funzionato per me; grazie! Ho dovuto scaricare il vaso di registrazione dei commons apache da qui: commons.apache.org/proper/commons-logging/download_logging.cgi Il mio codice in Main (): System.setProperty ("java.net.useSystemProxies", "true") ; System.out.println ("rilevamento dei proxy"); ExtendedProxyManager.init ();
Boris,

Cosa avrebbe l' xbootclasspatheffetto di deploy.jar, se non potessi portare quel vaso sul mio normale percorso di classe (quando corro senza webstart)?
Houtman,

1
in JDK 9, fallisce :( 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

Per me va bene:

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: mi baso sulla risposta di GHad.


Questa risposta non fornisce nulla che non sia già stato detto nelle altre risposte.
Simon Forsberg,

1

Come sottolineato in altre risposte, se è necessario utilizzare i proxy autenticati, non esiste un modo affidabile per farlo utilizzando esclusivamente le variabili della riga di comando, il che è fastidioso se si utilizza l'applicazione di qualcun altro e non si vuole fare confusione con il codice sorgente.

Will Iverson fornisce il suggerimento utile su Come utilizzare HttpProxy per connettersi a un host con autenticazione preventiva per utilizzare uno strumento di gestione proxy come Proxifier ( http://www.proxifier.com/ per Mac OS X e Windows) per gestirlo.

Ad esempio con Proxifier è possibile configurarlo per intercettare solo i comandi Java da gestire e reindirizzare tramite il suo proxy (autenticato). In questo caso, tuttavia, vorrai impostare i valori proxyHost e proxyPort su blank, ad esempio passare -Dhttp.proxyHost= -Dhttp.proxyPort=ai comandi java.


-1

È possibile utilizzare le variabili JVM http.proxy * se ci si trova in una JVM autonoma ma NON DOVREBBE modificare i loro script di avvio e / o farlo all'interno del proprio server delle applicazioni (tranne forse jboss o tomcat). Dovresti invece utilizzare l'API proxy JAVA (non System.setProperty) o utilizzare le opzioni di configurazione del fornitore. Sia WebSphere che WebLogic hanno modi ben definiti di impostare i proxy che sono molto più potenti di quello J2SE. Inoltre, per WebSphere e WebLogic è probabile che si rompa in qualche modo il server delle applicazioni sovrascrivendo gli script di avvio (in particolare i processi di interoperabilità del server in quanto si potrebbe dire loro di utilizzare anche il proxy ...).


-5

Penso che anche la configurazione di WINHTTP funzionerà.

Molti programmi, inclusi gli aggiornamenti di Windows, hanno problemi dietro il proxy. Configurando WINHTTP risolverà sempre questo tipo di problemi

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.