¿Cómo configuro el proxy para ser utilizado por la JVM?

Muchas veces, una aplicación Java necesita conectarse a Internet. El ejemplo más común ocurre cuando está leyendo un archivo XML y necesita descargar su esquema.

Estoy detrás de un servidor proxy. ¿Cómo configuro mi JVM para utilizar el proxy?

De la documentación de Java ( no de la API de javadoc):

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

Establezca los indicadores de JVM http.proxyHost y http.proxyPort al iniciar su JVM en la línea de comando. Esto generalmente se realiza en un script de shell (en Unix) o en un archivo bat (en Windows). Aquí está el ejemplo con el script de shell de Unix:

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

Cuando uso contenedores como JBoss o WebLogic, mi solución es editar los scripts de inicio suministrados por el proveedor.

Muchos desarrolladores están familiarizados con la API de Java (javadocs), pero muchas veces el rest de la documentación se pasa por alto. Contiene mucha información interesante: http://download.oracle.com/javase/6/docs/technotes/guides/


Actualización: si no desea utilizar el proxy para resolver algunos hosts locales / intranet, consulte el comentario de @Tomalak:

¡No olvide la propiedad http.nonProxyHosts!

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

Para usar la configuración del proxy del sistema:

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

O programáticamente

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

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

Para configurar un proxy HTTP / HTTPS y / o SOCKS mediante progtwigción:

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

Recuerde que los proxies HTTP y los proxies SOCKS operan a diferentes niveles en la stack de la red, por lo que puede usar uno u otro o ambos.

Puede establecer esos indicadores de forma programática de esta manera:

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

Simplemente devuelva los valores correctos de los métodos needsProxy() , getProxyHost() y getProxyPort() y puede llamar a este fragmento de código siempre que lo desee.

JVM usa el proxy para realizar llamadas HTTP

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

Esto puede usar un proxy de configuración de usuario

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

Puede establecer algunas propiedades sobre el servidor proxy como parámetros jvm

-Dhttp.proxyPort = 8080, proxyHost, etc.

pero si necesita pasar a través de un proxy de autenticación, necesita un autenticador como este ejemplo:

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

Ejemplo.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 } } 

Basado en esta respuesta: http://mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/200208.mbox/%3C494FD350388AD511A9DD00025530F33102F1DC2C@MMSX006%3E

leyendo un archivo XML y necesita descargar su esquema

Si confía en recuperar esquemas o DTD a través de Internet, está creando una aplicación lenta, hablante y frágil. ¿Qué ocurre cuando el servidor remoto que aloja el archivo tarda el tiempo de inactividad planeado o no planificado? Tu aplicación se rompe ¿Eso esta bien?

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

Las URL para esquemas y similares se consideran mejor como identificadores únicos. No como solicitudes para acceder realmente a ese archivo de forma remota. Haga alguna búsqueda en google en “Catálogo XML”. Un catálogo XML le permite alojar tales recursos localmente, resolviendo la lentitud, el chattiness y la fragilidad.

Básicamente es una copia en caché permanente del contenido remoto. Y eso está bien, ya que el contenido remoto nunca cambiará. Si alguna vez hay una actualización, estaría en una URL diferente. Hacer que la recuperación real del recurso a través de Internet sea especialmente tonta.

Establezca la propiedad java.net.useSystemProxies en true . Puede establecerlo, por ejemplo, a través de la variable de entorno JAVA_TOOL_OPTIONS . En Ubuntu, puede, por ejemplo, agregar la siguiente línea a .bashrc :

exportar JAVA_TOOL_OPTIONS + = “-Djava.net.useSystemProxies = true”

También estoy detrás del firewall, ¡esto funcionó para mí!

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

Combinando las respuestas de Sorter y javabrett / Leonel:

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

Agregue esto antes de conectarse a una URL detrás de 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"); 

A continuación se muestra cómo configurar en Java un proxy con usuario proxy y contraseña de proxy desde la línea de comandos, que es un caso muy común. En primer lugar, no debe guardar las contraseñas y los hosts en el código, como regla.

Pasar las propiedades del sistema en línea de comando con -D y configurarlas en el código con System.setProperty (“nombre”, “valor”) es equivalente.

Pero ten en cuenta esto

Ejemplo que funciona:

 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 

Pero lo siguiente no funciona

 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 

¡La única diferencia es la posición de las propiedades del sistema! (antes y después de la clase)

Si tiene caracteres especiales en la contraseña, puede ponerlo entre comillas “@ MyPass123%”, como en el ejemplo anterior.

Si accede a un servicio HTTPS, debe usar https.proxyHost, https.proxyPort, etc.

Si accede a un servicio HTTP, debe usar http.proxyHost, http.proxyPort, etc.

Esta es una actualización menor, pero desde Java 7, las conexiones proxy ahora se pueden crear mediante progtwigción en lugar de a través de las propiedades del sistema. Esto puede ser útil si:

  1. Proxy necesita rotar dinámicamente durante el tiempo de ejecución del progtwig
  2. Se deben usar múltiples proxies paralelos
  3. O simplemente haz tu código más limpio 🙂

Aquí hay un ejemplo artificial en 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() } 

Referencia completa: http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html

Recientemente descubrí la forma de permitir a JVM usar la configuración del proxy del navegador. Lo que debe hacer es agregar ${java.home}/lib/deploy.jar a su proyecto e ${java.home}/lib/deploy.jar la biblioteca de la siguiente manera:

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

Luego, la configuración de proxy está disponible para la API de Java a través de java.net.ProxySelector .

El único problema con este enfoque es que debe iniciar JVM con deploy.jar en bootclasspath, por ejemplo, java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar . Si alguien sabe cómo superar esta limitación, házmelo saber.

Funciona para mi:

 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: me baso en la respuesta de GHad.

Como se señala en otras respuestas, si necesita usar proxies autenticados, no hay una manera confiable de hacerlo usando meramente variables de línea de comando, lo cual es molesto si está usando la aplicación de otra persona y no quiere meterse con la código fuente.

Will Iverson hace la sugerencia útil al Usar HttpProxy para conectarse a un host con autenticación preemtive para usar una herramienta de administración de Proxy (como Proxifier) ​​( http://www.proxifier.com/ para Mac OS X y Windows) para manejar esto.

Por ejemplo, con Proxifier puede configurarlo para que solo intercepte comandos java que se administrarán y se redirigirán a través de su proxy (autenticado). Sin embargo, en este caso querrá establecer los valores de proxyHost y proxyPort en blanco; por ejemplo, pase -Dhttp.proxyHost= -Dhttp.proxyPort= a sus comandos java.

Si desea “Socks Proxy”, informe los argumentos de la máquina “socksProxyHost” y “socksProxyPort”.

p.ej

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

Además, si siempre está buscando descargar el mismo esquema, puede agregar el esquema a su classpath (sistema de archivos o JAR) y luego usar un EntityResolver personalizado.

Vea aquí para una discusión más completa de este enfoque.

Editar: Consulte la discusión de @Res.mejora.com / a / 0QMxE de CatalogResolver, que utiliza el enfoque EntityResolver:

 CatalogResolver cr = new CatalogResolver(); ... yourParser.setEntityResolver(cr) 

Puede utilizar las variables http.proxy * JVM si se encuentra dentro de una JVM independiente, pero NO DEBE modificar sus scripts de inicio y / o hacer esto dentro de su servidor de aplicaciones (excepto tal vez jboss o tomcat). En su lugar, debe utilizar la API JAVA Proxy (no System.setProperty) o utilizar las opciones de configuración propias del proveedor. Tanto WebSphere como WebLogic tienen formas muy definidas de configurar los proxies que son mucho más poderosos que el J2SE. Además, para WebSphere y WebLogic es probable que se rompa el servidor de aplicaciones de varias maneras anulando las secuencias de comandos de inicio (especialmente los procesos de interoperabilidad del servidor, ya que podría estar diciéndoles que también usen su proxy …).

Creo que la configuración de WINHTTP también funcionará.

Muchos progtwigs, incluidas las actualizaciones de Windows, tienen problemas detrás del proxy. Al configurar WINHTTP siempre solucionará este tipo de problemas