¿Cómo configuro el proxy para que lo use la JVM?

308

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 puedo configurar mi JVM para usar el proxy?

Leonel
fuente
La documentación de Oracle en torno a esto parece bastante obsoleta (aunque probablemente sea válida). Aquí hay algo más moderno de Spring: docs.spring.io/spring-integration/reference/html/…
nobar

Respuestas:

350

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 las banderas JVM http.proxyHosty http.proxyPortcuando inicie su JVM en la línea de comando. Esto generalmente se hace 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 utilizo contenedores como JBoss o WebLogic, mi solución es editar los scripts de inicio proporcionados por el proveedor.

Muchos desarrolladores están familiarizados con la API de Java (javadocs), pero muchas veces se pasa por alto el resto de la documentación. 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:

¡Además, no olvide la propiedad http.nonProxyHosts!

-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com‌​|etc"
Leonel
fuente
109
+1. Además, no te olvides de la http.nonProxyHostspropiedad! (uso de la siguiente manera: -Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc")
Tomalak
3
Hola chicos, ¿cómo pueden incluir el nombre de usuario y la contraseña en esto también? Gracias
Joeblackdev
8
@Joeblackdev mira http.proxyUser y http.proxyPassword
aasukisuki el
44
@aasukisuki http.proxyUsery http.proxyPasswordno son propiedades del sistema Java. Son para el cliente Apache HTTP.
Marqués de Lorne
24
Además, no olvide configurar https.proxyHosty https.proxyPortpara HTTP.
C-Otto
103

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

gr5
fuente
El argumento de jvm de configuración impresionante funciona para mí como un encanto ... Gracias
nanosoft
Usé este código para deshabilitar el proxy por valor "falso" en mi SSLSocket. Gracias.
Fer
1
Quizás sea porque mi proxy requiere autenticación, pero esto no funcionó para mí. Ojalá lo hiciera.
Simon Forsberg
3
Esto no funciona con los archivos Proxy Auto-Config (PAC), consulte stackoverflow.com/questions/10324996/…
Michael_S
80

Para configurar un proxy HTTP / HTTPS y / o SOCKS mediante programació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 en diferentes niveles en la pila de la red, por lo que puede usar uno u otro o ambos.

Chris Carruthers
fuente
44
Si se establece "java.net.socks.username / password", ¿por qué también configurar un autenticador?
Marqués de Lorne
1
por qué no es "con.setRequest ..." la estafa no se reconoce. Qué bibliotecas se necesitan para esto.
Randnum
1
+1 para la opción de proxy de calcetines, ya que a veces el proxy http no puede resolver mi problema
manuzhang
1
En mis pruebas, funciona si solo configura el Autenticador predeterminado (no es necesario configurar las propiedades de autenticación)
Drew Stephens
1
No funciona si solo las propiedades del sistema. Creo que las propiedades java.net.socks. (Nombre de usuario | contraseña) no hacen nada.
Drew Stephens
46

Puede establecer esas banderas mediante programación 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()puede llamar a este fragmento de código cuando lo desee.

GHad
fuente
34
"proxySet" no hace nada. Prueba: configúrelo en "falso". No hay y nunca ha habido tal propiedad en el JDK, a pesar de varios libros y referencias en línea. Provenía del desaparecido HotJavaBean, un navegador encapsulado, que murió en 1998.
Marqués de Lorne
2
¿Realmente son los nombres de propiedad sin http / https?
Betlista
18
Esto es incorrecto en tres aspectos: 1: como se mencionó, no hay ningún elemento "proxySet"; 2: "proxyHost" y "proxyPort" deben ser "http.proxyHost" y "http.proxyPort" (o el equivalente 'https'); 3: System.getProperties (). Put (X, Y) no es lo mismo que System.setProperty (X, Y). Aparte de eso, sin embargo, gran respuesta.
Rob Cranfill
1
@RobCranfill 1: "proxySet" solía ser un indicador no estándar que necesitaba un JDK antiguo, pero ya no es necesario; 2: "proxyHost" y "proxyPort" funcionan, el "http". el prefijo solo los restringe al protocolo HTTP (similar a "https"), 3: aquí tienes razón.
toolforger
24

JVM usa el proxy para hacer llamadas HTTP

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

Esto puede usar el proxy de configuración del usuario

System.setProperty("java.net.useSystemProxies", "true");
sarath
fuente
Usar en System.setPropertylugar deSystem.getProperties().put(...)
Simon Forsberg
12

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

-Dhttp.proxyPort = 8080, proxyHost, etc.

pero si necesita pasar por 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;
    }
}

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

    }
}

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

Alex S.
fuente
esto no funciona. Si aún no está autenticado, la primera línea de la función principal obtiene un montón de valores nulos y el código se detiene. Esto no ayuda a alguien a autenticar su jvm para que pueda hacer llamadas URL a través de un proxy.
Randnum
12

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
Bamboomy
fuente
10

Establecer la java.net.useSystemProxiespropiedad a true. Puede configurarlo, 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:

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

Mihai Capotă
fuente
9

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. No debe guardar contraseñas y hosts en el código, como regla general.

Pasar las propiedades del sistema en la línea de comandos con -D y establecerlas 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 ponerla entre comillas "@ MyPass123%", como en el ejemplo anterior.

Si accede a un servicio HTTPS, debe usarlo https.proxyHost, https.proxyPortetc.

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

Andreas Panagiotidis
fuente
55
ProxyUser y proxyPassword no son propiedades del sistema Java, sino propiedades del cliente Apache HTTP, por lo que esto no funciona en todos los casos.
THelper
8

leyendo un archivo XML y necesita descargar su esquema

Si cuenta con recuperar esquemas o DTD a través de Internet, está creando una aplicación lenta, habladora y frágil. ¿Qué sucede cuando ese servidor remoto que aloja el archivo toma tiempo de inactividad planificado 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 a ese archivo de forma remota. Realice búsquedas en google en el "catálogo XML". Un catálogo XML le permite alojar dichos recursos localmente, resolviendo la lentitud, el chat 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, sería en una URL diferente. Hacer que la recuperación real del recurso a través de Internet sea especialmente tonta.

John M
fuente
7

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

Si desea "Socks Proxy", informe los argumentos de VM "socksProxyHost" y "socksProxyPort".

p.ej

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

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");
Clasificador
fuente
44
http.proxyUsery http.proxyPasswordno son propiedades del sistema Java. Son para el cliente Apache HTTP.
Marqués de Lorne
Usar en System.setPropertylugar deSystem.getProperties().put(...)
Simon Forsberg
4

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

  1. El proxy debe rotarse dinámicamente durante el tiempo de ejecución del programa
  2. Se deben usar múltiples proxys paralelos
  3. O simplemente haga su 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

Philip M.
fuente
2
Esto es desde Java 1.5, no 1.7.
Marqués de Lorne
3

Recientemente descubrí la forma de permitir que JVM use la configuración del proxy del navegador. Lo que debe hacer es agregar ${java.home}/lib/deploy.jara su proyecto e iniciar 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;
    }
}

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

El único problema con este enfoque es que necesita iniciar JVM con deploy.jarbootclasspath, por ejemplo java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar. Si alguien sabe cómo superar esta limitación, avíseme.

dma_k
fuente
1
Desearía poder votar esto varias veces, es la única solución que funcionó para mí; ¡gracias! Tuve que descargar el jar de registro de apache commons desde aquí: commons.apache.org/proper/commons-logging/download_logging.cgi Mi código en Main (): System.setProperty ("java.net.useSystemProxies", "true") ; System.out.println ("detección de proxies"); ExtendedProxyManager.init ();
Boris
¿Qué efecto tendría el xbootclasspathapuntar a deploy.jar, no podría llevar ese jar a mi classpath normal (cuando se ejecuta sin inicio web)?
Houtman
1
en JDK 9, falla :( 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

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.

Viet Tran
fuente
Esta respuesta no proporciona nada que no se haya dicho en las otras respuestas.
Simon Forsberg
1

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

Will Iverson hace la sugerencia útil en Uso de HttpProxy para conectarse a un host con autenticación preventiva 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 los comandos de Java que se administrarán y redirigirán a través de su proxy (autenticado). Sin embargo, querrá establecer los valores proxyHost y proxyPort en blanco en este caso, por ejemplo, pasar -Dhttp.proxyHost= -Dhttp.proxyPort=a los comandos de Java.

patdevelop
fuente
-1

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 de proxy JAVA (no System.setProperty) o utilizar las propias opciones de configuración del proveedor. Tanto WebSphere como WebLogic tienen formas muy definidas de configurar los servidores proxy que son mucho más potentes que el J2SE. Además, para WebSphere y WebLogic es probable que rompa su servidor de aplicaciones de alguna manera al anular los scripts de inicio (particularmente los procesos de interoperabilidad del servidor, ya que podría estar diciéndoles que también usen su proxy ...).


fuente
-5

Creo que configurar WINHTTP también funcionará.

Muchos programas, incluidas las actualizaciones de Windows, tienen problemas con el proxy. Al configurar WINHTTP siempre se solucionarán este tipo de problemas

nylas
fuente