Sering kali, aplikasi Java perlu terhubung ke Internet. Contoh paling umum terjadi ketika sedang membaca file XML dan perlu mengunduh skemanya.
Saya di belakang server proxy. Bagaimana saya bisa mengatur JVM saya untuk menggunakan proxy?
Sering kali, aplikasi Java perlu terhubung ke Internet. Contoh paling umum terjadi ketika sedang membaca file XML dan perlu mengunduh skemanya.
Saya di belakang server proxy. Bagaimana saya bisa mengatur JVM saya untuk menggunakan proxy?
Jawaban:
Dari dokumentasi Java ( bukan API javadoc):
http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html
Atur bendera JVM http.proxyHost
dan http.proxyPort
ketika memulai JVM Anda pada baris perintah. Ini biasanya dilakukan dalam skrip shell (di Unix) atau file bat (di Windows). Inilah contoh dengan skrip shell Unix:
JAVA_FLAGS=-Dhttp.proxyHost=10.0.0.100 -Dhttp.proxyPort=8800
java ${JAVA_FLAGS} ...
Saat menggunakan wadah seperti JBoss atau WebLogic, solusi saya adalah mengedit skrip start-up yang disediakan oleh vendor.
Banyak pengembang yang akrab dengan Java API (javadocs), tetapi sering kali sisa dokumentasi diabaikan. Ini berisi banyak informasi menarik: http://download.oracle.com/javase/6/docs/technotes/guides/
Pembaruan: Jika Anda tidak ingin menggunakan proxy untuk menyelesaikan beberapa host lokal / intranet, periksa komentar dari @Tomalak:
Juga jangan lupa properti http.nonProxyHosts!
-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc"
http.nonProxyHosts
properti! (gunakan seperti ini: -Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc"
)
http.proxyUser
dan http.proxyPassword
bukan properti sistem Java. Itu untuk klien HTTP Apache.
https.proxyHost
dan https.proxyPort
untuk HTTPs.
Untuk menggunakan pengaturan proxy sistem:
java -Djava.net.useSystemProxies=true ...
Atau secara terprogram:
System.setProperty("java.net.useSystemProxies", "true");
Sumber: http://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html
Untuk mengatur HTTP / HTTPS dan / atau proxy SOCKS secara terprogram:
...
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;
}
}
...
Ingatlah bahwa proksi HTTP dan proksi SOCKS beroperasi pada tingkat yang berbeda di tumpukan jaringan, sehingga Anda dapat menggunakan satu atau yang lain atau keduanya.
Anda dapat mengatur bendera tersebut secara terprogram seperti ini:
if (needsProxy()) {
System.setProperty("http.proxyHost",getProxyHost());
System.setProperty("http.proxyPort",getProxyPort());
} else {
System.setProperty("http.proxyHost","");
System.setProperty("http.proxyPort","");
}
Cukup kembalikan nilai yang benar dari metode needsProxy()
, getProxyHost()
dan getProxyPort()
dan Anda dapat memanggil potongan kode ini kapan pun Anda mau.
JVM menggunakan proxy untuk melakukan panggilan HTTP
System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");
Ini dapat menggunakan proxy pengaturan pengguna
System.setProperty("java.net.useSystemProxies", "true");
System.setProperty
sebagai gantiSystem.getProperties().put(...)
Anda dapat mengatur beberapa properti tentang server proxy sebagai parameter jvm
-Dhttp.proxyPort = 8080, proxyHost, dll.
tetapi jika Anda perlu melewati proxy autentikasi, Anda memerlukan autentikator seperti contoh ini:
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;
}
}
Contoh.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
}
}
Berdasarkan jawaban ini: http://mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/200208.mbox/%3C494FD350388AD511A9DD00025530F33102F1DC2C@MMSX006%3E
Setel java.net.useSystemProxies
properti ke true
. Anda dapat mengaturnya, misalnya, melalui variabel lingkungan JAVA_TOOL_OPTIONS . Di Ubuntu, Anda dapat, misalnya, menambahkan baris berikut ke .bashrc
:
ekspor JAVA_TOOL_OPTIONS + = "-Djava.net.useSystemProxies = true"
Berikut ini menunjukkan cara mengatur proxy Java dengan pengguna proxy dan kata sandi proxy dari baris perintah, yang merupakan kasus yang sangat umum. Anda tidak boleh menyimpan kata sandi dan host di kode, sebagai aturan di tempat pertama.
Melewati properti sistem dalam baris perintah dengan -D dan mengaturnya dalam kode dengan System.setProperty ("name", "value") adalah setara.
Tapi perhatikan ini
Contoh yang berfungsi:
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
Tetapi yang berikut ini tidak berfungsi :
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
Satu-satunya perbedaan adalah posisi properti sistem! (sebelum dan sesudah kelas)
Jika Anda memiliki karakter khusus dalam kata sandi, Anda diizinkan memasukkannya dalam tanda kutip "@ MyPass123%", seperti dalam contoh di atas.
Jika Anda mengakses layanan HTTPS, Anda harus menggunakan https.proxyHost
, https.proxyPort
dll.
Jika Anda mengakses layanan HTTP, Anda harus menggunakan http.proxyHost
, http.proxyPort
dll.
membaca file XML dan perlu mengunduh skemanya
Jika Anda mengandalkan skema pengambilan atau DTD melalui internet, Anda sedang membangun aplikasi yang lambat, cerewet, dan rapuh. Apa yang terjadi ketika server jauh yang meng-host file mengambil downtime yang direncanakan atau tidak terencana? Aplikasi Anda rusak. Apakah itu oke?
Lihat http://xml.apache.org/commons/components/resolver/resolver-article.html#s.catalog.files
URL untuk skema dan sejenisnya paling baik dianggap sebagai pengidentifikasi unik. Bukan sebagai permintaan untuk benar-benar mengakses file itu dari jarak jauh. Lakukan pencarian google di "katalog XML". Katalog XML memungkinkan Anda untuk meng-host sumber daya tersebut secara lokal, menyelesaikan kelambatan, mengobrol dan kerapuhan.
Ini pada dasarnya adalah salinan konten remote yang di-cache secara permanen. Dan itu tidak masalah, karena konten jarak jauh tidak akan pernah berubah. Jika ada pembaruan, itu akan berada di URL yang berbeda. Membuat pengambilan sumber daya yang sebenarnya melalui internet sangat konyol.
Saya juga di belakang firewall, ini bekerja untuk saya !!
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();
Jika Anda ingin "Socks Proxy", informasikan argumen VM "socksProxyHost" dan "socksProxyPort".
misalnya
java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main
Tambahkan ini sebelum Anda terhubung ke URL di belakang 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");
http.proxyUser
dan http.proxyPassword
bukan properti sistem Java. Itu untuk klien HTTP Apache.
System.setProperty
sebagai gantiSystem.getProperties().put(...)
Ini adalah pembaruan kecil, tetapi sejak Java 7, koneksi proxy sekarang dapat dibuat secara pemrograman daripada melalui properti sistem. Ini mungkin berguna jika:
Berikut adalah contoh yang dibuat di 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()
}
Referensi Lengkap: http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html
Baru-baru ini saya menemukan cara untuk memungkinkan JVM menggunakan pengaturan proxy browser. Yang perlu Anda lakukan adalah menambahkan ${java.home}/lib/deploy.jar
ke proyek Anda dan masuk ke perpustakaan seperti berikut:
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;
}
}
Setelah itu pengaturan proxy tersedia untuk Java API via java.net.ProxySelector
.
Satu-satunya masalah dengan pendekatan ini adalah Anda harus menjalankan JVM dengan deploy.jar
di bootclasspath misalnya java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar
. Jika seseorang tahu cara mengatasi batasan ini, beri tahu saya.
xbootclasspath
diterapkan deploy.jar untuk efeknya, tidak bisakah saya membawa jar itu ke classpath normal saya (ketika berjalan tanpa webstart)?
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
Itu bekerja untuk saya:
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: Saya mendasarkan pada jawaban GHad.
Seperti yang ditunjukkan dalam jawaban lain, jika Anda perlu menggunakan proxy terotentikasi, tidak ada cara yang dapat diandalkan untuk melakukan ini murni menggunakan variabel baris perintah - yang mengganggu jika Anda menggunakan aplikasi orang lain dan tidak ingin mengacaukan dengan Kode sumber.
Will Iverson membuat saran yang bermanfaat di Menggunakan HttpProxy untuk terhubung ke host dengan otentikasi preemtive untuk menggunakan alat manajemen Proxy seperti Proxifier ( http://www.proxifier.com/ untuk Mac OS X dan Windows) untuk menangani hal ini.
Misalnya dengan Proxifier, Anda dapat mengaturnya hanya untuk mencegat perintah java yang akan dikelola dan dialihkan melalui proxy (yang diotentikasi). Anda akan ingin mengeset nilai proxyHost dan proxyPort menjadi kosong dalam kasus ini, misalnya, melewatinya-Dhttp.proxyHost= -Dhttp.proxyPort=
perintah java Anda.
Anda dapat menggunakan variabel http.proxy * JVM jika Anda berada dalam JVM mandiri tetapi Anda TIDAK HARUS memodifikasi skrip startup mereka dan / atau melakukan ini dalam server aplikasi Anda (kecuali mungkin jboss atau tomcat). Alih-alih, Anda harus menggunakan JAVA Proxy API (bukan System.setProperty) atau menggunakan opsi konfigurasi vendor sendiri. Baik WebSphere dan WebLogic memiliki cara yang sangat jelas untuk mengatur proksi yang jauh lebih kuat daripada J2SE. Selain itu, untuk WebSphere dan WebLogic Anda mungkin akan memecah server aplikasi Anda dengan cara-cara kecil dengan menimpa skrip startup (terutama proses interop server karena Anda mungkin memberi tahu mereka untuk menggunakan proxy Anda juga ...).