Часто Java-приложение должно подключаться к Интернету. Наиболее распространенный пример происходит, когда он читает файл XML и ему нужно загрузить свою схему.
Я за прокси-сервером. Как я могу настроить свою JVM на использование прокси?
Часто Java-приложение должно подключаться к Интернету. Наиболее распространенный пример происходит, когда он читает файл XML и ему нужно загрузить свою схему.
Я за прокси-сервером. Как я могу настроить свою JVM на использование прокси?
Ответы:
Из документации Java ( не API Javadoc):
http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html
Установите флаги JVM http.proxyHost
и http.proxyPort
при запуске JVM в командной строке. Обычно это делается в сценарии оболочки (в Unix) или в файле bat (в Windows). Вот пример со сценарием оболочки Unix:
JAVA_FLAGS=-Dhttp.proxyHost=10.0.0.100 -Dhttp.proxyPort=8800
java ${JAVA_FLAGS} ...
При использовании таких контейнеров, как JBoss или WebLogic, мое решение заключается в редактировании сценариев запуска, предоставляемых поставщиком.
Многие разработчики знакомы с Java API (javadocs), но во многих случаях остальная часть документации игнорируется. Он содержит много интересной информации: http://download.oracle.com/javase/6/docs/technotes/guides/
Обновление: если вы не хотите использовать прокси для разрешения некоторых локальных / интрасетевых хостов, ознакомьтесь с комментарием @Tomalak:
Также не забывайте свойство http.nonProxyHosts!
-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc"
http.nonProxyHosts
собственность! (использование так: -Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc"
)
http.proxyUser
и http.proxyPassword
не являются системными свойствами Java. Они для HTTP-клиента Apache.
https.proxyHost
и https.proxyPort
для HTTP.
Чтобы использовать настройку прокси системы:
java -Djava.net.useSystemProxies=true ...
Или программно:
System.setProperty("java.net.useSystemProxies", "true");
Источник: http://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html
Чтобы установить HTTP / HTTPS и / или SOCKS прокси программно:
...
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;
}
}
...
Помните, что HTTP-прокси и SOCKS-прокси работают на разных уровнях сетевого стека, поэтому вы можете использовать один или другой или оба.
Вы можете установить эти флаги программно следующим образом:
if (needsProxy()) {
System.setProperty("http.proxyHost",getProxyHost());
System.setProperty("http.proxyPort",getProxyPort());
} else {
System.setProperty("http.proxyHost","");
System.setProperty("http.proxyPort","");
}
Просто вернуть правильные значения из методов needsProxy()
, getProxyHost()
и , getProxyPort()
и вы можете вызвать этот фрагмент кода , когда вы хотите.
JVM использует прокси для выполнения HTTP-вызовов
System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");
Это может использовать настройки прокси пользователя
System.setProperty("java.net.useSystemProxies", "true");
System.setProperty
вместоSystem.getProperties().put(...)
Вы можете установить некоторые свойства прокси-сервера в качестве параметров jvm
-Dhttp.proxyPort = 8080, proxyHost и т. Д.
но если вам нужно пройти через прокси-сервер аутентификации, вам нужен такой аутентификатор, как в следующем примере:
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
}
}
На основании этого ответа: http://mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/200208.mbox/%3C494FD350388AD511A9DD00025530F33102F1DC2C@MMSX006%3E
Установите java.net.useSystemProxies
свойство в true
. Вы можете установить его, например, через переменную среды JAVA_TOOL_OPTIONS . В Ubuntu вы можете, например, добавить следующую строку .bashrc
:
export JAVA_TOOL_OPTIONS + = "-Djava.net.useSystemProxies = true"
Ниже показано, как установить в Java прокси с прокси-пользователем и паролем прокси из командной строки, что является очень распространенным случаем. Не стоит сохранять пароли и хосты в коде, как правило, в первую очередь.
Передача системных свойств в командной строке с помощью -D и установка их в коде с помощью System.setProperty («имя», «значение») эквивалентны.
Но учтите это
Пример, который работает:
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
Но следующее не работает :
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
Разница лишь в расположении системных свойств! (до и после занятий)
Если у вас есть специальные символы в пароле, вы можете поместить его в кавычки "@ MyPass123%", как в примере выше.
Если вы получаете доступ к службе HTTPS, вы должны использовать https.proxyHost
и https.proxyPort
т. Д.
Если вы получаете доступ к службе HTTP, вам придется использовать http.proxyHost
и http.proxyPort
т. Д.
чтение файла XML и необходимо загрузить его схему
Если вы рассчитываете получить схемы или DTD через Интернет, вы создаете медленное, болтливое и хрупкое приложение. Что происходит, когда этот удаленный сервер, на котором размещается файл, берет запланированные или незапланированные простои? Ваше приложение ломается. Это нормально?
См. Http://xml.apache.org/commons/components/resolver/resolver-article.html#s.catalog.files.
URL-адреса для схем и т.п. лучше всего рассматривать как уникальные идентификаторы. Не так, как запросы на удаленный доступ к этому файлу. Выполните поиск в Google по каталогу XML. Каталог XML позволяет размещать такие ресурсы локально, устраняя медлительность, болтливость и хрупкость.
Это в основном постоянно кэшированная копия удаленного контента. И это нормально, так как удаленный контент никогда не изменится. Если когда-нибудь будет обновление, оно будет по другому URL. Делать фактический поиск ресурса через интернет особенно глупо.
Я также за брандмауэром, это сработало для меня!
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();
Если вы хотите «Socks Proxy», сообщите аргументы VM «socksProxyHost» и «socksProxyPort».
например
java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main
Добавьте это, прежде чем подключаться к URL-адресу за прокси.
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
и http.proxyPassword
не являются системными свойствами Java. Они для HTTP-клиента Apache.
System.setProperty
вместоSystem.getProperties().put(...)
Это незначительное обновление, но, начиная с Java 7, прокси-соединения теперь могут создаваться программно, а не через системные свойства. Это может быть полезно, если:
Вот надуманный пример в 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()
}
Полная ссылка: http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html
Недавно я обнаружил способ разрешить JVM использовать настройки прокси браузера. Что вам нужно сделать, это добавить ${java.home}/lib/deploy.jar
в свой проект и запустить библиотеку, как показано ниже:
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;
}
}
После этого настройки прокси доступны для API Java через java.net.ProxySelector
.
Единственная проблема с этим подходом состоит в том, что вам нужно запустить JVM с помощью deploy.jar
bootclasspath, например java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar
. Если кто-то знает, как преодолеть это ограничение, дайте мне знать.
xbootclasspath
влияние окажет указание на deploy.jar, не могу ли я перенести этот jar на мой обычный classpath (при работе без веб-запуска)?
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
Это подходит для меня:
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: Я основываюсь на ответе GHad.
Как указано в других ответах, если вам нужно использовать прокси-серверы с проверкой подлинности, нет надежного способа сделать это исключительно с помощью переменных командной строки - что раздражает, если вы используете чужое приложение и не хотите связываться с исходный код.
Уилл Айверсон (Will Iverson) делает полезное предложение в разделе Использование HttpProxy для подключения к хосту с предварительной аутентификацией для использования инструмента управления Proxy, такого как Proxifier ( http://www.proxifier.com/ для Mac OS X и Windows), для решения этой проблемы .
Например, с Proxifier вы можете настроить его только на перехват команд java, которые будут управляться и перенаправляться через его (аутентифицированный) прокси. Однако в этом случае вы захотите установить значения proxyHost и proxyPort пустыми, например, передать -Dhttp.proxyHost= -Dhttp.proxyPort=
свои команды Java.
Вы можете использовать переменные http.proxy * JVM, если вы находитесь в автономной JVM, но НЕ ДОЛЖНЫ изменять их сценарии запуска и / или делать это на сервере приложений (за исключением, возможно, jboss или tomcat). Вместо этого вы должны использовать JAVA Proxy API (не System.setProperty) или использовать собственные параметры конфигурации поставщика. Как в WebSphere, так и в WebLogic есть очень определенные способы настройки прокси, которые намного мощнее, чем J2SE. Кроме того, для WebSphere и WebLogic вы, скорее всего, нарушите работу своего сервера приложений, переопределив сценарии запуска (особенно процессы взаимодействия с сервером, поскольку вы, возможно, говорите им также использовать ваш прокси-сервер ...).