Bagaimana cara mengatur proxy yang akan digunakan oleh JVM

308

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?

Leonel
sumber
The dokumentasi Oracle sekitar ini tampaknya cukup basi (meskipun masih mungkin berlaku). Berikut ini sesuatu yang lebih modern dari Spring: docs.spring.io/spring-integration/reference/html/…
nobar

Jawaban:

350

Dari dokumentasi Java ( bukan API javadoc):

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

Atur bendera JVM http.proxyHostdan http.proxyPortketika 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"
Leonel
sumber
109
+1. Juga jangan lupa http.nonProxyHostsproperti! (gunakan seperti ini: -Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc")
Tomalak
3
Hai teman-teman, bagaimana Anda bisa memasukkan nama pengguna dan kata sandi ini juga? Terima kasih
Joeblackdev
8
@ Joeblackdev lihat http.proxyUser dan http.proxyPassword
aasukisuki
4
@aasukisuki http.proxyUserdan http.proxyPasswordbukan properti sistem Java. Itu untuk klien HTTP Apache.
Marquis of Lorne
24
Juga, jangan lupa untuk mengkonfigurasi https.proxyHostdan https.proxyPortuntuk HTTPs.
C-Otto
103

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

gr5
sumber
Pengaturan mengagumkan argumentasi jvm bekerja untuk saya seperti pesona .. Terima kasih
nanosoft
Saya menggunakan kode ini untuk menonaktifkan proxy dengan nilai "false" pada SSLSocket saya. Terima kasih.
Fer
1
Mungkin karena proxy saya memerlukan otentikasi, tetapi ini tidak berhasil untuk saya. Saya berharap itu terjadi.
Simon Forsberg
3
Ini tidak berfungsi dengan file Proxy Auto-Config (PAC), lihat stackoverflow.com/questions/10324996/…
Michael_S
80

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.

Chris Carruthers
sumber
4
Jika "java.net.socks.username / password" diset, mengapa juga mengatur Authenticator?
Marquis of Lorne
1
mengapa tidak "con.setRequest ..." con tidak dikenali. Perpustakaan apa yang dibutuhkan untuk ini.
Randnum
1
+1 untuk opsi proxy kaus kaki karena kadang-kadang proxy http tidak dapat menyelesaikan masalah saya
manuzhang
1
Dalam pengujian saya, ini berfungsi jika Anda hanya menetapkan Authenticator default — tidak perlu mengatur properti otentikasi
Drew Stephens
1
Tidak berfungsi jika Anda hanya properti sistem. Memikirkan properti java.net.socks. (Nama pengguna | kata sandi) tidak melakukan apa-apa.
Drew Stephens
46

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.

GHad
sumber
34
"proxySet" tidak melakukan apa pun. Bukti: setel ke "false". Tidak ada dan tidak pernah ada properti seperti itu di JDK, meskipun ada berbagai buku dan referensi online. Itu datang dari HotJavaBean yang sudah lama mati, browser yang dienkapsulasi, meninggal pada sekitar tahun 1998.
Marquis of Lorne
2
Benarkah nama properti tanpa http / https?
Betlista
18
Ini salah dalam tiga hal: 1: seperti yang disebutkan, tidak ada item "proxySet"; 2: "proxyHost" dan "proxyPort" harus "http.proxyHost" dan "http.proxyPort" (atau yang setara dengan 'https'); 3: System.getProperties (). Put (X, Y) tidak sama dengan System.setProperty (X, Y). Selain itu, meskipun - jawaban yang bagus.
Rob Cranfill
1
@RobCranfill 1: "proxySet" digunakan untuk menjadi bendera non-standar yang diperlukan oleh JDK lama tetapi tidak diperlukan lagi; 2: "proxyHost" dan "proxyPort" berfungsi, "http." awalan hanya membatasi mereka ke protokol HTTP (mirip untuk "https."), 3: di sini Anda benar.
toolforger
24

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");
sarath
sumber
Gunakan System.setPropertysebagai gantiSystem.getProperties().put(...)
Simon Forsberg
12

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

Alex S.
sumber
ini tidak bekerja. jika Anda belum mengautentikasi, baris pertama pada fungsi utama mendapat banyak nilai nol dan kode berhenti. Ini tidak membantu seseorang mengautentikasi jvm mereka sehingga mereka dapat melakukan panggilan URL melalui proxy.
Randnum
12

Menggabungkan jawaban Sorter dan javabrett / Leonel:

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

Setel java.net.useSystemProxiesproperti 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"

Mihai Capotă
sumber
9

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.proxyPortdll.

Jika Anda mengakses layanan HTTP, Anda harus menggunakan http.proxyHost, http.proxyPortdll.

Andreas Panagiotidis
sumber
5
ProxyUser dan proxyPassword bukan properti sistem Java, tetapi properti klien HTTP Apache jadi ini tidak bekerja dalam semua kasus.
THelper
8

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.

John M
sumber
7

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();
Pallavi
sumber
5

Jika Anda ingin "Socks Proxy", informasikan argumen VM "socksProxyHost" dan "socksProxyPort".

misalnya

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

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");
Tukang sortir
sumber
4
http.proxyUserdan http.proxyPasswordbukan properti sistem Java. Itu untuk klien HTTP Apache.
Marquis of Lorne
Gunakan System.setPropertysebagai gantiSystem.getProperties().put(...)
Simon Forsberg
4

Ini adalah pembaruan kecil, tetapi sejak Java 7, koneksi proxy sekarang dapat dibuat secara pemrograman daripada melalui properti sistem. Ini mungkin berguna jika:

  1. Proxy perlu diputar secara dinamis selama runtime program
  2. Proxy paralel berganda perlu digunakan
  3. Atau cukup bersihkan kode Anda :)

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

Philip M.
sumber
2
Ini karena Java 1.5, bukan 1.7.
Marquis of Lorne
3

Baru-baru ini saya menemukan cara untuk memungkinkan JVM menggunakan pengaturan proxy browser. Yang perlu Anda lakukan adalah menambahkan ${java.home}/lib/deploy.jarke 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.jardi bootclasspath misalnya java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar. Jika seseorang tahu cara mengatasi batasan ini, beri tahu saya.

dma_k
sumber
1
Saya berharap saya dapat memperbaiki ini beberapa kali, itu adalah satu-satunya solusi yang bekerja untuk saya; Terima kasih! Saya harus mengunduh toples log apache commons dari sini: commons.apache.org/proper/commons-logging/download_logging.cgi Kode saya di Main (): System.setProperty ("java.net.useSystemProxies", "true") ; System.out.println ("mendeteksi proksi"); ExtendedProxyManager.init ();
Boris
Apa yang ingin xbootclasspathditerapkan deploy.jar untuk efeknya, tidak bisakah saya membawa jar itu ke classpath normal saya (ketika berjalan tanpa webstart)?
Houtman
1
di JDK 9, gagal :( 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

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.

Viet Tran
sumber
Jawaban ini tidak memberikan apa pun yang belum dikatakan dalam jawaban lain.
Simon Forsberg
1

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.

pengembangan
sumber
-1

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 ...).


sumber
-5

Saya pikir mengkonfigurasi WINHTTP juga akan berfungsi.

Banyak program termasuk Pembaruan Windows mengalami masalah di balik proksi. Dengan mengatur WINHTTP akan selalu memperbaiki masalah seperti ini

nylas
sumber