Pregunta

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?

¿Fue útil?

Solución

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

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

Establecer las banderas de JVM http.proxyHost y http.proxyPort al iniciar 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 uso 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/


Actualizar : Si no desea utilizar proxy para resolver algunos hosts locales/de 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"

Otros consejos

Para utilizar 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 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 red, por lo que puede usar uno, el otro o ambos.

Puede configurar 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 devuelve los valores correctos de los métodos. needsProxy(), getProxyHost() y getProxyPort() y puedes llamar a este fragmento de código cuando quieras.

JVM usa el proxy para realizar llamadas HTTP

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

Esto puede utilizar el proxy de configuración del 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

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

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, comunicativa y frágil.¿Qué sucede cuando el servidor remoto que aloja el archivo sufre un tiempo de inactividad planificado o no planificado?Tu aplicación falla.¿Eso esta bien?

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

Es mejor considerar las URL para esquemas y similares como identificadores únicos.No como solicitudes para acceder a ese archivo de forma remota.Haga algunas búsquedas en Google sobre "catálogo XML".Un catálogo XML le permite alojar dichos recursos localmente, resolviendo la lentitud, la charlatanería y la fragilidad.

Básicamente es una copia almacenada 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á en una URL diferente.Hacer que la recuperación real del recurso a través de Internet sea especialmente tonta.

Selecciona el java.net.useSystemProxies propiedad a true.Puede configurarlo, por ejemplo, a través del JAVA_TOOL_OPTIONS variable ambiental.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();

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

Pasar las propiedades del sistema en la 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 ponerla entre comillas "@MyPass123%", como en el ejemplo anterior.

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

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

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

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 propiedades del sistema.Esto puede resultar útil si:

  1. El proxy debe rotarse dinámicamente durante el tiempo de ejecución del programa.
  2. Es necesario utilizar varios servidores proxy 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

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

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

Luego, 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.jar en bootclasspath, p. java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar.Si alguien sabe cómo superar esta limitación, hágamelo 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");
    }
}

PD:Me baso en la respuesta de GHad.

Como se señala en otras respuestas, si necesita utilizar servidores proxy autenticados, no existe una forma 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 útil sugerencia en Usar HttpProxy para conectarse a un host con autenticación preventiva utilizar 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 redirigirán a través de su proxy (autenticado).Sin embargo, en este caso querrás establecer los valores de proxyHost y proxyPort en blanco, p.Aconteció en -Dhttp.proxyHost= -Dhttp.proxyPort= a sus comandos java.

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

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

Editar:Ver @me.yahoo.com/a/0QMxE's discusión sobre CatalogResolver, que utiliza el enfoque EntityResolver:

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

Puede utilizar las variables JVM http.proxy* si está dentro de una JVM independiente, pero NO DEBE modificar sus scripts de inicio y/o hacer esto dentro de su servidor de aplicaciones (excepto quizás jboss o tomcat).En su lugar, debe utilizar la API de proxy JAVA (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 potentes que el J2SE.Además, para WebSphere y WebLogic es probable que rompa su servidor de aplicaciones en pequeñas formas al anular los scripts de inicio (particularmente los procesos de interoperabilidad del servidor, ya que podría decirles que también usen su proxy...).

creo que configurando WINHTTP también funcionará.

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top