Como eu configuro o proxy para ser usado pela JVM

308

Muitas vezes, um aplicativo Java precisa se conectar à Internet. O exemplo mais comum acontece quando está lendo um arquivo XML e precisa fazer o download de seu esquema.

Estou atrás de um servidor proxy. Como posso configurar minha JVM para usar o proxy?

Leonel
fonte
A documentação do Oracle em torno disso parece bastante antiga (embora ainda seja provavelmente válida). Aqui está algo mais moderno do Spring: docs.spring.io/spring-integration/reference/html/…
nobar

Respostas:

350

Na documentação Java ( não na API javadoc):

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

Defina os sinalizadores da JVM http.proxyHoste http.proxyPortao iniciar sua JVM na linha de comandos. Isso geralmente é feito em um script de shell (no Unix) ou em um arquivo bat (no Windows). Aqui está o exemplo com o script de shell Unix:

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

Ao usar contêineres como JBoss ou WebLogic, minha solução é editar os scripts de inicialização fornecidos pelo fornecedor.

Muitos desenvolvedores estão familiarizados com a API Java (javadocs), mas muitas vezes o restante da documentação é negligenciado. Ele contém muitas informações interessantes: http://download.oracle.com/javase/6/docs/technotes/guides/


Atualização: se você não deseja usar o proxy para resolver alguns hosts locais / intranet, confira o comentário em @Tomalak:

Além disso, não esqueça a propriedade http.nonProxyHosts!

-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com‌​|etc"
Leonel
fonte
109
+1. Também não se esqueça da http.nonProxyHostspropriedade! (uso como este: -Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc")
Tomalak
3
Oi pessoal, como você pode incluir também o nome de usuário e a senha? Graças
Joeblackdev
8
@Joeblackdev veja http.proxyUser e http.proxyPassword
aasukisuki
4
@aasukisuki http.proxyUsere http.proxyPasswordnão são propriedades do sistema Java. Eles são para o cliente HTTP Apache.
Marquês de Lorne
24
Além disso, não esqueça de configurar https.proxyHoste https.proxyPortpara HTTPs.
C # Otto
103

Para usar a configuração de proxy do sistema:

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

Ou programaticamente:

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

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

gr5
fonte
Impressionantes obras configuração JVM argumento para me como charme .. Obrigado
Nanosoft
Eu usei esse código para desativar o proxy pelo valor "false" no meu SSLSocket. Obrigado.
Fer
1
Talvez seja porque meu proxy exija autenticação, mas isso não funcionou para mim. Eu gostaria que sim.
Simon Forsberg
3
Isso não funciona com arquivos de configuração automática de proxy (PAC), consulte stackoverflow.com/questions/10324996/…
Michael_S
80

Para definir um proxy HTTP / HTTPS e / ou SOCKS programaticamente:

...

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

...

Lembre-se de que os proxies HTTP e os proxies SOCKS operam em níveis diferentes na pilha da rede, para que você possa usar um ou outro ou ambos.

Chris Carruthers
fonte
4
Se "java.net.socks.username / password" estiver definido, por que também definir um autenticador?
Marquês de Lorne #
1
por que não é "con.setRequest ..." o con não é reconhecido. Quais bibliotecas são necessárias para isso.
Randnum 08/12/19
1
+1 para a opção de proxy como, por vezes, proxy HTTP não pode resolver o meu problema meias
manuzhang
1
Em meus testes, ele funciona se você só definir o padrão autenticador-não há necessidade de definir as propriedades de autenticação
de Drew Stephens
1
Não funciona se você apenas as propriedades do sistema. Considera que as propriedades java.net.socks. (Nome de usuário | senha) não fazem nada.
Drew Stephens
46

Você pode definir esses sinalizadores programaticamente desta maneira:

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

Basta retornar os valores corretos a partir dos métodos needsProxy(), getProxyHost()e getProxyPort()e você pode chamar este trecho de código quando quiser.

GHad
fonte
34
"proxySet" não faz nada. Prova: defina como "false". Não existe e nunca houve essa propriedade no JDK, apesar de vários livros e referências on-line. Ele veio do HotJavaBean longo extinta, um navegador encapsulado, uma morte em cerca de 1998.
Marquês de Lorne
2
Realmente são os nomes das propriedades sem http / https?
Betlista
18
Isso está errado em três aspectos: 1: como mencionado, não há item "proxySet"; 2: "proxyHost" e "proxyPort" precisam ser "http.proxyHost" e "http.proxyPort" (ou o equivalente 'https'); 3: System.getProperties (). Put (X, Y) não é o mesmo que System.setProperty (X, Y). Fora isso, porém - ótima resposta.
precisa
1
@RobCranfill 1: "proxySet" costumava ser um sinalizador não padrão que era necessário por um JDK antigo, mas não é mais necessário; 2: "proxyHost" e "proxyPort" funcionam, o "http". O prefixo restringe-os apenas ao protocolo HTTP (semelhante a "https."), 3: aqui você está certo.
toolforger
24

A JVM usa o proxy para fazer chamadas HTTP

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

Isso pode usar o proxy de configuração do usuário

System.setProperty("java.net.useSystemProxies", "true");
sarath
fonte
Use em System.setPropertyvez deSystem.getProperties().put(...)
Simon Forsberg
12

Você pode definir algumas propriedades sobre o servidor proxy como parâmetros jvm

-Dhttp.proxyPort = 8080, proxyHost, etc.

mas se você precisar passar por um proxy de autenticação, precisará de um autenticador como este exemplo:

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

    }
}

Com base nesta resposta: http://mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/200208.mbox/%3C494FD350388AD511A9DD00025530F33102F1DC2C@MMSX006%3E

Alex. S.
fonte
isso não funciona. se você ainda não está autenticado, a primeira linha na função principal obtém vários valores nulos e o código para. Isso não ajuda alguém a autenticar sua jvm, para que possa fazer chamadas de URL por meio de um proxy.
Randnum 8/12
12

Combinando as respostas de Sorter e javabrett / Leonel:

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

Defina a java.net.useSystemProxiespropriedade como true. Você pode configurá-lo, por exemplo, através da variável de ambiente JAVA_TOOL_OPTIONS . No Ubuntu, você pode, por exemplo, adicionar a seguinte linha a .bashrc:

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

Mihai Capotă
fonte
9

A seguir, mostramos como configurar em Java um proxy com usuário proxy e senha de proxy na linha de comandos, que é um caso muito comum. Você não deve salvar senhas e hosts no código, como regra geral.

Passar as propriedades do sistema na linha de comando com -D e defini-las no código com System.setProperty ("name", "value") é equivalente.

Mas observe isso

Exemplo 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

Mas o seguinte não 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

A única diferença é a posição das propriedades do sistema! (antes e depois da aula)

Se você tiver caracteres especiais na senha, poderá colocá-lo entre aspas "@ MyPass123%", como no exemplo acima.

Se você acessar um serviço HTTPS, você tem que usar https.proxyHost, https.proxyPortetc.

Se você acessar um serviço HTTP, você tem que usar http.proxyHost, http.proxyPortetc.

Andreas Panagiotidis
fonte
5
ProxyUser e proxyPassword não são propriedades do sistema Java, mas propriedades do cliente HTTP Apache, portanto, isso não funciona em todos os casos.
THelper
8

lendo um arquivo XML e precisa fazer download de seu esquema

Se você está contando com a recuperação de esquemas ou DTDs pela Internet, está criando um aplicativo lento, falador e frágil. O que acontece quando o servidor remoto que hospeda o arquivo leva um tempo de inatividade planejado ou não planejado? Seu aplicativo é interrompido. Tudo bem?

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

URLs para esquemas e afins são mais bem pensados ​​como identificadores exclusivos. Não como solicitações para acessar esse arquivo remotamente. Faça uma pesquisa no google no "catálogo XML". Um catálogo XML permite que você hospede esses recursos localmente, resolvendo a lentidão, a propriedade e a fragilidade.

É basicamente uma cópia permanentemente em cache do conteúdo remoto. E tudo bem, já que o conteúdo remoto nunca muda. Se houver alguma atualização, ela estará em um URL diferente. Tornar a recuperação real do recurso pela Internet especialmente boba.

John M
fonte
7

Também estou atrás de firewall, isso funcionou para mim !!

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
fonte
5

Se você deseja "Socks Proxy", informe os argumentos da VM "socksProxyHost" e "socksProxyPort".

por exemplo

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

Adicione isso antes de se conectar a um URL atrás de um 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");
Classificador
fonte
4
http.proxyUsere http.proxyPasswordnão são propriedades do sistema Java. Eles são para o cliente HTTP Apache.
Marquês de Lorne
Use em System.setPropertyvez deSystem.getProperties().put(...)
Simon Forsberg
4

Esta é uma atualização secundária, mas desde o Java 7, as conexões de proxy agora podem ser criadas de forma programática, e não através das propriedades do sistema. Isso pode ser útil se:

  1. O proxy precisa ser rotacionado dinamicamente durante o tempo de execução do programa
  2. Vários proxies paralelos precisam ser usados
  3. Ou apenas faça seu código mais limpo :)

Aqui está um exemplo artificial no 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()
}

Referência completa: http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html

Philip M.
fonte
2
Isso ocorre desde Java 1.5, não 1.7.
Marquês de Lorne
3

Recentemente, descobri a maneira de permitir que a JVM use as configurações de proxy do navegador. O que você precisa fazer é adicionar ${java.home}/lib/deploy.jarao seu projeto e iniciar a biblioteca da seguinte maneira:

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, as configurações de proxy estão disponíveis para a API Java via java.net.ProxySelector.

O único problema com essa abordagem é que você precisa iniciar a JVM deploy.jarno bootclasspath, por exemplo java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar. Se alguém souber como superar essa limitação, me avise.

dma_k
fonte
1
Eu gostaria de poder votar isso várias vezes, é a única solução que funcionou para mim; obrigado! Eu tive que baixar o jar de logon do apache commons a partir daqui: commons.apache.org/proper/commons-logging/download_logging.cgi Meu código em Main (): System.setProperty ("java.net.useSystemProxies", "true") ; System.out.println ("detectando proxies"); ExtendedProxyManager.init ();
Boris
O que o xbootclasspathapontar para deploy.jar teria efeito?
21718 Houtman
1
no JDK 9, ele falha :( 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

Isso funciona para mim:

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: Baseio-me na resposta do GHad.

Viet Tran
fonte
Esta resposta não fornece nada que ainda não tenha sido dito nas outras respostas.
Simon Forsberg
1

Conforme indicado em outras respostas, se você precisar usar proxies autenticados, não há uma maneira confiável de fazer isso puramente usando variáveis ​​de linha de comando - o que é irritante se você estiver usando o aplicativo de outra pessoa e não quiser mexer com o Código fonte.

Will Iverson faz a sugestão útil em Como usar o HttpProxy para conectar-se a um host com autenticação preventiva para usar uma ferramenta de gerenciamento de proxy como o Proxifier ( http://www.proxifier.com/ para Mac OS X e Windows) para lidar com isso.

Por exemplo, com o Proxifier, você pode configurá-lo para interceptar apenas comandos java para serem gerenciados e redirecionados por meio de seu proxy (autenticado). Você vai querer definir os valores proxyHost e proxyPort como em branco neste caso, por exemplo, passe -Dhttp.proxyHost= -Dhttp.proxyPort=para seus comandos java.

patdevelop
fonte
-1

Você pode utilizar as variáveis ​​http.proxy * JVM se estiver dentro de uma JVM autônoma, mas NÃO DEVE modificar os scripts de inicialização e / ou fazer isso no servidor de aplicativos (exceto talvez o jboss ou o tomcat). Em vez disso, você deve utilizar a API do Proxy JAVA (não System.setProperty) ou utilizar as opções de configuração do próprio fornecedor. O WebSphere e o WebLogic têm maneiras muito definidas de configurar os proxies que são muito mais poderosos que o J2SE. Além disso, para o WebSphere e o WebLogic, você provavelmente interromperá o servidor de aplicativos de pequenas maneiras, substituindo os scripts de inicialização (particularmente os processos de interoperabilidade do servidor, como você pode estar dizendo a eles para usar seu proxy também ...).


fonte
-5

Eu acho que configurar o WINHTTP também funcionará.

Muitos programas, incluindo as atualizações do Windows, estão tendo problemas por trás do proxy. A configuração do WINHTTP sempre corrigirá esse tipo de problema

nylas
fonte