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?
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?
Risposte:
Dalla documentazione Java ( non dall'API javadoc):
http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html
Impostare i flag JVM http.proxyHost
e http.proxyPort
quando 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"
http.nonProxyHosts
proprietà! (uso in questo modo: -Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc"
)
http.proxyUser
e http.proxyPassword
non sono proprietà di sistema Java. Sono per il client HTTP Apache.
https.proxyHost
e https.proxyPort
per HTTPs.
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
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.
È 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.
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");
System.setProperty
invece diSystem.getProperties().put(...)
È 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
Impostare la java.net.useSystemProxies
proprietà su true
. È possibile impostarlo, ad esempio, tramite la variabile ambientale JAVA_TOOL_OPTIONS . In Ubuntu, ad esempio, puoi aggiungere la seguente riga a .bashrc
:
export JAVA_TOOL_OPTIONS + = "-Djava.net.useSystemProxies = true"
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.proxyPort
ecc.
Se accedi a un servizio HTTP, devi usare http.proxyHost
, http.proxyPort
ecc.
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.
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();
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
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");
http.proxyUser
e http.proxyPassword
non sono proprietà di sistema Java. Sono per il client HTTP Apache.
System.setProperty
invece diSystem.getProperties().put(...)
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:
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
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.jar
al 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.jar
bootclasspath ad es java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar
. Se qualcuno sa come superare questa limitazione, fammelo sapere.
xbootclasspath
effetto di deploy.jar, se non potessi portare quel vaso sul mio normale percorso di classe (quando corro senza webstart)?
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
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.
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.
È 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 ...).