Багато разів додатку 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
:
експортувати 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", повідомте про аргументи "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;
}
}
Після цього налаштування проксі доступні для Java API через java.net.ProxySelector
.
Єдина проблема такого підходу полягає в тому, що вам потрібно запустити JVM з deploy.jar
bootclasspath, наприклад java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar
. Якщо хтось знає, як подолати це обмеження, дайте мені знати.
xbootclasspath
вказувало б на вказівку на layout.jar, чи не можу я перенести цю банку на звичайний класний шлях (коли працює без веб-запуску)?
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.
Як вказується в інших відповідях, якщо вам потрібно використовувати автентифіковані проксі, немає надійного способу зробити це виключно за допомогою змінних командного рядка - що дратує, якщо ви використовуєте чужу програму і не хочете возитися з вихідний код.
Вілл Іверсон робить корисну пропозицію при використанні програми HttpProxy для підключення до хоста з попередньою автентифікацією, щоб використовувати інструмент управління проксі, наприклад Proxifier ( http://www.proxifier.com/ для Mac OS X та Windows) для вирішення цього питання.
Наприклад, за допомогою Proxifier ви можете налаштувати його лише на перехоплення команд Java, якими керує та перенаправляє їх через (автентифікований) проксі. Ви хочете встановити значення proxyHost та proxyPort порожніми в цьому випадку, хоча, наприклад, перейдіть -Dhttp.proxyHost= -Dhttp.proxyPort=
до своїх команд Java.
Ви можете використовувати змінні http.proxy * JVM, якщо ви знаходитесь в окремому JVM, але НЕ МОЖЕ НЕ змінювати їхні сценарії запуску та / або робити це на вашому сервері прикладних програм (за винятком можливо jboss або tomcat). Натомість слід використовувати API проксі-сервера JAVA (не System.setProperty) або використовувати власні параметри налаштування постачальника. І WebSphere, і WebLogic мають дуже визначені способи налаштування проксі, які є набагато потужнішими, ніж J2SE. Крім того, для WebSphere та WebLogic ви, швидше за все, зламаєте ваш сервер додатків, перекриваючи сценарії запуску (зокрема, процеси інтеропування сервера, як ви могли б сказати їм також використовувати ваш проксі ...).