Làm cách nào để tôi đặt proxy được JVM sử dụng


308

Nhiều lần, một ứng dụng Java cần kết nối với Internet. Ví dụ phổ biến nhất xảy ra khi nó đang đọc một tệp XML và cần tải xuống lược đồ của nó.

Tôi đứng sau một máy chủ proxy. Làm cách nào tôi có thể thiết lập JVM của mình để sử dụng proxy?


Các tài liệu của Oracle xung quanh điều này có vẻ khá cũ (mặc dù vẫn có thể hợp lệ). Đây là một cái gì đó hiện đại hơn từ mùa xuân: docs.spring.io/spring-integration/reference/html/iêu
nobar

Câu trả lời:


350

Từ tài liệu Java ( không phải API javadoc):

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

Đặt các cờ JVM http.proxyHosthttp.proxyPortkhi bắt đầu JVM của bạn trên dòng lệnh. Điều này thường được thực hiện trong một tập lệnh shell (trong Unix) hoặc tập tin bat (trong Windows). Đây là ví dụ với tập lệnh shell Unix:

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

Khi sử dụng các thùng chứa như JBoss hoặc WebLogic, giải pháp của tôi là chỉnh sửa các tập lệnh khởi động được cung cấp bởi nhà cung cấp.

Nhiều nhà phát triển đã quen thuộc với API Java (javadocs), nhưng nhiều lần phần còn lại của tài liệu bị bỏ qua. Nó chứa rất nhiều thông tin thú vị: http://doad.oracle.com/javase/6/docs/technotes/guides/


Cập nhật: Nếu bạn không muốn sử dụng proxy để giải quyết một số máy chủ lưu trữ cục bộ / mạng nội bộ, hãy xem nhận xét từ @Tomalak:

Cũng đừng quên thuộc tính http.nonProxyhosts!

-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com‌​|etc"

109
+1. Cũng đừng quên http.nonProxyHoststài sản! (sử dụng như thế này -Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc":)
Tomalak

3
Xin chào các bạn, làm thế nào bạn có thể bao gồm tên người dùng và mật khẩu trong này? Cảm ơn
Joeblackdev

8
@Joeblackdev xem http.proxyUser và http.proxyPassword
aasukisuki

4
@aasukisuki http.proxyUserhttp.proxyPasswordkhông phải là thuộc tính hệ thống Java. Chúng dành cho máy khách HTTP Apache.
Hầu tước Lorne

24
Ngoài ra, đừng quên cấu hình https.proxyHosthttps.proxyPortcho HTTP.
C-Otto

103

Để sử dụng thiết lập proxy hệ thống:

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

Hoặc theo chương trình:

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

Nguồn: http://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properIES.html


Thiết lập tuyệt vời jvm tranh luận làm việc cho tôi như quyến rũ .. Cảm ơn
nanosoft

Tôi đã sử dụng mã này để vô hiệu hóa proxy theo giá trị "sai" trên SSLSocket của mình. Cảm ơn.
Fer

1
Có lẽ đó là do proxy của tôi yêu cầu xác thực, nhưng điều này không hiệu quả với tôi. Tôi ước nó đã làm.
Simon Forsberg

3
Điều này không hoạt động với các tệp Proxy Auto-Config (PAC), xem stackoverflow.com/questions/10324996/
mẹo

80

Để đặt proxy HTTP / HTTPS và / hoặc SOCKS theo chương trình:

...

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

...

Hãy nhớ rằng proxy HTTP và proxy SOCKS hoạt động ở các cấp khác nhau trong ngăn xếp mạng, vì vậy bạn có thể sử dụng một hoặc một hoặc cả hai.


4
Nếu "java.net.socks.username / password" được đặt, tại sao cũng đặt Authenticator?
Hầu tước Lorne

1
tại sao không phải là "con.setRequest ..." thì con không được công nhận. Những thư viện cần thiết cho việc này.
Randnum

1
+1 cho tùy chọn proxy vớ vì đôi khi http proxy không thể giải quyết vấn đề của tôi
manuzhang

1
Trong thử nghiệm của tôi, nó hoạt động nếu bạn chỉ đặt Authenticator mặc định không cần thiết lập các thuộc tính xác thực
Drew Stephens

1
Không hoạt động nếu bạn chỉ thuộc tính hệ thống. Methinks các thuộc tính java.net.socks. (Tên người dùng | mật khẩu) không làm gì cả.
Drew Stephens

46

Bạn có thể đặt các cờ đó theo cách lập trình theo cách này:

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

Chỉ cần trả lại giá trị ngay từ những phương pháp needsProxy(), getProxyHost()getProxyPort()và bạn có thể gọi đoạn mã này bất cứ khi nào bạn muốn.


34
"Proxy set" không làm gì cả. Bằng chứng: đặt thành "sai". Không có và chưa bao giờ có một tài sản như vậy trong JDK, nhiều sách và tài liệu tham khảo trực tuyến khác nhau. Nó đến từ HotJavaBean, một trình duyệt được gói gọn, đã chết một cái chết vào khoảng năm 1998.
Hầu tước Lorne

2
Thực sự là tên tài sản mà không có http / https?
Betlista

18
Điều này sai ở ba cách tính: 1: như đã đề cập, không có mục "proxy Set"; 2: "proxyhost" và "proxyPort" cần phải là "http.proxyhost" và "http.proxyPort" (hoặc tương đương 'https'); 3: System.getProperIES (). Put (X, Y) không giống với System.setProperty (X, Y). Khác hơn thế, mặc dù - câu trả lời tuyệt vời.
Rob Cranfill


1
@RobCranfill 1: "proxy Set" từng là cờ không chuẩn mà cần có bởi một JDK cũ nhưng không còn cần thiết nữa; 2: "proxyhost" và "proxyPort" hoạt động, "http." tiền tố chỉ giới hạn chúng trong giao thức HTTP (tương tự như "https."), 3: ở đây bạn đúng.
toolforger

24

JVM sử dụng proxy để thực hiện các cuộc gọi HTTP

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

Điều này có thể sử dụng proxy cài đặt người dùng

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

Sử dụng System.setPropertythay vìSystem.getProperties().put(...)
Simon Forsberg

12

Bạn có thể đặt một số thuộc tính về máy chủ proxy làm tham số jvm

-Dhttp.proxyPort = 8080, proxyhost, v.v.

nhưng nếu bạn cần thông qua một proxy xác thực, bạn cần một trình xác thực như ví dụ này:

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

Ví dụ

    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

    }
}

Dựa trên câu trả lời này: http://mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/200208.mbox/%3C494FD350388AD511A9DD00025530F33102F1DC2C@MMSX006%3E


cái này không hoạt động nếu bạn chưa được xác thực, dòng đầu tiên trong hàm chính sẽ nhận được một loạt các giá trị null và mã dừng lại. Điều này không giúp ai đó xác thực jvm của họ để họ có thể thực hiện cuộc gọi URL thông qua proxy.
Randnum

12

Kết hợp câu trả lời của Sorter và javabrett / Leonel:

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


9

Phần sau đây cho thấy cách đặt trong Java một proxy bằng mật khẩu người dùng và mật khẩu proxy từ dòng lệnh, đây là trường hợp rất phổ biến. Bạn không nên lưu mật khẩu và máy chủ lưu trữ trong mã, như một quy tắc ở nơi đầu tiên.

Truyền các thuộc tính hệ thống trong dòng lệnh với -D và đặt chúng trong mã với System.setProperty ("name", "value") là tương đương.

Nhưng lưu ý điều này

Ví dụ hoạt động:

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

Nhưng những điều sau đây không hoạt động :

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

Sự khác biệt duy nhất là vị trí của các thuộc tính hệ thống! (trước và sau giờ học)

Nếu bạn có các ký tự đặc biệt trong mật khẩu, bạn được phép đặt nó trong dấu ngoặc kép "@ MyPass123%", như trong ví dụ trên.

Nếu bạn truy cập dịch vụ HTTPS, bạn phải sử dụng https.proxyHost, https.proxyPortv.v.

Nếu bạn truy cập dịch vụ HTTP, bạn phải sử dụng http.proxyHost, http.proxyPortv.v.


5
ProxyUser và proxyPassword không phải là thuộc tính hệ thống Java, nhưng thuộc tính máy khách HTTP HTTP vì vậy điều này không hoạt động trong mọi trường hợp.
THelper

8

đọc một tệp XML và cần tải xuống lược đồ của nó

Nếu bạn đang tính đến việc truy xuất các lược đồ hoặc DTD qua internet, bạn đang xây dựng một ứng dụng chậm, trò chuyện, dễ vỡ. Điều gì xảy ra khi máy chủ từ xa lưu trữ tệp mất thời gian dự kiến ​​hoặc không có kế hoạch? Ứng dụng của bạn bị hỏng. Ổn chứ?

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

URL cho các lược đồ và tương tự được coi là định danh duy nhất. Không phải là yêu cầu để thực sự truy cập tập tin đó từ xa. Thực hiện một số tìm kiếm google trên "Danh mục XML". Một danh mục XML cho phép bạn lưu trữ các tài nguyên đó cục bộ, giải quyết sự chậm chạp, chậm chạp và mong manh.

Về cơ bản, nó là một bản sao lưu vĩnh viễn của nội dung từ xa. Và không sao, vì nội dung từ xa sẽ không bao giờ thay đổi. Nếu có một bản cập nhật, nó sẽ ở một URL khác. Làm cho việc lấy tài nguyên thực tế qua internet đặc biệt là ngớ ngẩn.


7

Tôi cũng đứng sau tường lửa, điều này làm việc cho tôi !!

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();

5

Nếu bạn muốn "Vớ Proxy", hãy thông báo cho các đối số VM "vớProxyhost" và "vớProxyPort".

ví dụ

java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main

4

Thêm phần này trước khi bạn kết nối với một URL phía sau 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");

4
http.proxyUserhttp.proxyPasswordkhông phải là thuộc tính hệ thống Java. Chúng dành cho máy khách HTTP Apache.
Hầu tước Lorne

Sử dụng System.setPropertythay vìSystem.getProperties().put(...)
Simon Forsberg

4

Đây là một bản cập nhật nhỏ, nhưng kể từ Java 7, các kết nối proxy giờ đây có thể được tạo bằng lập trình thay vì thông qua các thuộc tính hệ thống. Điều này có thể hữu ích nếu:

  1. Proxy cần được xoay động trong thời gian chạy chương trình
  2. Nhiều proxy song song cần được sử dụng
  3. Hoặc chỉ cần làm cho mã của bạn sạch hơn :)

Đây là một ví dụ giả định trong 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()
}

Tham khảo đầy đủ: http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html


2
Đây là từ Java 1.5, không phải 1.7.
Hầu tước Lorne

3

Gần đây tôi đã phát hiện ra cách cho phép JVM sử dụng cài đặt proxy trình duyệt. Những gì bạn cần làm là thêm ${java.home}/lib/deploy.jarvào dự án của bạn và khởi tạo thư viện như sau:

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

Sau đó, các cài đặt proxy có sẵn cho API Java thông qua java.net.ProxySelector.

Vấn đề duy nhất với cách tiếp cận này là bạn cần khởi động JVM với deploy.jartrong bootgrouppath, vd java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar. Nếu ai đó biết cách vượt qua giới hạn này, hãy cho tôi biết.


1
Tôi ước tôi có thể nâng cao điều này nhiều lần, đó là giải pháp duy nhất hiệu quả với tôi; cảm ơn bạn! Tôi đã phải tải xuống tệp ghi nhật ký apache commons từ đây: commons.apache.org/proper/commons-logging/doad_logging.cgi Mã của tôi trong Main (): System.setProperty ("java.net.useSystemProxies", "true") ; System.out.println ("phát hiện proxy"); ExtendedProxyManager.init ();
Boris

Việc xbootclasspathtrỏ đến triển khai.jar sẽ có tác dụng gì, tôi không thể đưa cái bình đó lên đường dẫn lớp thông thường của tôi (khi chạy mà không có webstart)?
Houtman

1
trong JDK 9, nó thất bại :( 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

Nó ổn với tôi:

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: Tôi dựa trên câu trả lời của GHad.


Câu trả lời này không cung cấp bất cứ điều gì chưa được nói trong các câu trả lời khác.
Simon Forsberg

1

Như được chỉ ra trong các câu trả lời khác, nếu bạn cần sử dụng proxy xác thực, không có cách nào đáng tin cậy để thực hiện việc này hoàn toàn bằng cách sử dụng các biến dòng lệnh - gây phiền nhiễu nếu bạn đang sử dụng ứng dụng của người khác và không muốn gây rối với mã nguồn.

Iverson sẽ đưa ra gợi ý hữu ích tại Sử dụng HttpProxy để kết nối với máy chủ có xác thực định trước để sử dụng công cụ quản lý Proxy như Proxifier ( http://www.proxifier.com/ cho Mac OS X và Windows) để xử lý việc này.

Ví dụ với Proxifier, bạn có thể thiết lập nó để chỉ chặn các lệnh java được quản lý và chuyển hướng thông qua proxy (xác thực) của nó. Tuy nhiên, bạn sẽ muốn đặt các giá trị proxyhost và proxyPort trong trường hợp này, ví dụ: truyền vào -Dhttp.proxyHost= -Dhttp.proxyPort=các lệnh java của bạn.


-1

Bạn có thể sử dụng các biến JVM http.proxy * nếu bạn ở trong một JVM độc lập nhưng bạn KHÔNG NÊN sửa đổi các tập lệnh khởi động của chúng và / hoặc thực hiện điều này trong máy chủ ứng dụng của bạn (ngoại trừ có thể là jboss hoặc tomcat). Thay vào đó, bạn nên sử dụng API Proxy JAVA (không phải System.setProperty) hoặc sử dụng các tùy chọn cấu hình của nhà cung cấp. Cả WebSphere và WebLogic đều có những cách rất rõ ràng để thiết lập các proxy mạnh hơn nhiều so với J2SE. Ngoài ra, đối với WebSphere và WebLogic, bạn có thể sẽ phá vỡ máy chủ ứng dụng của mình bằng cách ghi đè các tập lệnh khởi động (đặc biệt là các quy trình xen kẽ của máy chủ như bạn có thể bảo chúng sử dụng proxy của mình ...).


-5

Tôi nghĩ rằng cấu hình WINHTTP cũng sẽ hoạt động.

Nhiều chương trình bao gồm Windows Updates đang gặp vấn đề đằng sau proxy. Bằng cách thiết lập WINHTTP sẽ luôn khắc phục loại sự cố này

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.