Java 程序全局代理设置
Java Archive
在 Java 命令行中,可以使用 -D 参数设置系统属性。这个参数可以用来设置任何系统属性,包括自定义的属性,这里我们只关注网络相关的系统属性。
只需要在启动 jar 程序时使用这些参数,就能让原本不支持代理设置的 jar 程序挂上代理了。
设置 HTTP 代理示例:
1
Java -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=8080 -Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=8080 -Dhttp.nonProxyHosts= -jar .\example.jar
注:在 powershell 中需要将参数使用
'
或"
包裹起来,如:Java '-Dhttp.proxyHost=127.0.0.1' '-Dhttp.proxyPort=8080' -jar .\example.jar
。
设置 SOCKS5 代理示例:
1
java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=1080 -jar example.jar
网络相关部分系统属性:
属性 | 简述 |
---|---|
socksProxyHost | socks 代理服务器的主机名 |
socksProxyPort | socks 代理服务器的端口号 |
http.proxyHost | http 代理服务器的主机名 |
http.proxyPort | http 代理服务器的端口号 |
http.proxyUser | 用于在 http 代理服务器进行认证的用户 |
http.proxyPassword | 用于在 http 代理服务器进行认证的密码 |
http.nonProxyHosts | 指定直连 ip,不走 http/https 代理 |
Java Code
设置全局代理:System.setProperty(K,V)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.*;
public class ProxyUtils {
public static void main(String[] args) throws Exception {
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7897));
System.out.println(verifyProxy(proxy));
}
/**
* 验证 HTTP/SOCKS 代理
* @param proxy 输入代理设置(java.net.Proxy 对象)
* Proxy proxy = new Proxy(java.net.Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 7897));
* @return 返回通过 SOCKS 服务器代理后的公网 IP
*/
public static String verifyProxy(Proxy proxy) throws Exception {
URL url = new URL("https://myip.ipip.net"); // Simple API to get your public IP
URLConnection connection = proxy == null ? url.openConnection() : url.openConnection(proxy);
try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
return in.readLine();
}
}
/**
* 验证全局 HTTP/SOCKS 代理,无需传入参数
* @return 返回通过 SOCKS 服务器代理后的公网 IP
*/
public static String verifyGlobalProxy() throws Exception {
URL url = new URL("https://myip.ipip.net"); // Simple API to get your public IP
URLConnection connection = url.openConnection();
try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
return in.readLine();
}
}
public static void setupGlobalSocksProxy(String host, Integer port) throws Exception {
setupGlobalSocksProxy(host,port , null,null );
}
/**
* 通过 System.setProperty(K,V) 设置网络代理相关系统属性,来设置 SOCKS 代理。
* 注:该方式存在弊端,可能会因为外部系统代理的优先级高于内部程序的设置,而导致程序中的代理设置失效。
* 代码参考:https://stackoverflow.com/questions/120797/how-do-i-set-the-proxy-to-be-used-by-the-jvm
* @param host SOCKS 代理服务器地址
* @param port SOCKS 代理服务器端口
* @param username 认证用户
* @param password 认证密码
*/
public static void setupGlobalSocksProxy(String host, Integer port, String username, String password) {
// Set the global SOCKS proxy settings
System.setProperty("socksProxyHost", host);
System.setProperty("socksProxyPort", port.toString());
// If authentication is required
if (username != null && password != null) {
System.setProperty("java.net.socks.username", username);
System.setProperty("java.net.socks.password", password);
Authenticator.setDefault(new ProxyAuth(username, password));
}
}
public static void setupGlobalHttpProxy(String host, Integer port) throws Exception {
setupGlobalHttpProxy(host,port , null,null );
}
/**
* 通过 System.setProperty(K,V) 设置网络代理相关系统属性,来设置 HTTP/HTTPS 代理。
* 注:该方式存在弊端,可能会因为外部系统代理的优先级高于内部程序的设置,而导致程序中的代理设置失效。
* 代码参考:https://stackoverflow.com/questions/120797/how-do-i-set-the-proxy-to-be-used-by-the-jvm
* @param host HTTP/HTTPS 代理服务器地址
* @param port HTTP/HTTPS 代理服务器端口
* @param username 认证用户
* @param password 认证密码
*/
public static void setupGlobalHttpProxy(String host, Integer port, String username, String password) {
System.setProperty("http.proxyHost", host);
System.setProperty("http.proxyPort", port.toString());
System.setProperty("https.proxyHost", host);
System.setProperty("https.proxyPort", port.toString());
if (username != null && password != null) {
System.setProperty("http.proxyUser", username);
System.setProperty("http.proxyPassword", password);
System.setProperty("https.proxyUser", username);
System.setProperty("https.proxyPassword", password);
System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
System.setProperty("jdk.https.auth.tunneling.disabledSchemes", "");
Authenticator.setDefault(new ProxyAuth(username, password));
}
}
/**
* 通过 System.clearProperty(K,V) 清除网络代理相关系统属性。
* 注:可清除外部系统代理设置效果。
* 建议先使用该方法清除外部系统代理设置后,再使用 setupGlobalSocksProxy(host, port) 方法设置全局代理,这样能确保程序中的代理设置生效。
*/
public static void unsetSystemProxy() throws Exception {
System.clearProperty("http.proxyHost");
System.clearProperty("http.proxyPort");
System.clearProperty("https.proxyHost");
System.clearProperty("https.proxyPort");
System.clearProperty("socksProxyHost");
System.clearProperty("socksProxyPort");
}
static class ProxyAuth extends Authenticator {
private PasswordAuthentication auth;
private ProxyAuth(String username, String password) {
auth = new PasswordAuthentication(username, password == null ? new char[]{} : password.toCharArray());
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return auth;
}
}
}
设置全局代理:ProxySelector
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import java.io.IOException;
import java.net.*;
import java.util.Collections;
import java.util.List;
import static xxx.ProxyUtils.verifyGlobalProxy;
public class CustomProxySelector extends ProxySelector {
public static void main(String[] args) throws Exception {
// 设置自定义的 ProxySelector
ProxySelector.setDefault(new CustomProxySelector("127.0.0.1", 7897, ProxyType.HTTP));
// 设置全局的 Authenticator
Authenticator.setDefault(new ProxyAuthenticator("admin", "123456"));
// 请求 https://myip.ipip.net 验证代理出口地址
System.out.println(verifyGlobalProxy());
// 清除 ProxySelector
ProxySelector.setDefault(null);
System.out.println(verifyGlobalProxy());
}
// 枚举定义代理类型
public enum ProxyType {
HTTP, SOCKS
}
private final Proxy proxy;
public CustomProxySelector(String proxyHost, int proxyPort, ProxyType proxyType) {
if (proxyType == ProxyType.HTTP) {
// HTTP 代理
this.proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
} else if (proxyType == ProxyType.SOCKS) {
// SOCKS 代理
this.proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(proxyHost, proxyPort));
} else {
// 不使用代理
this.proxy = Proxy.NO_PROXY;
}
}
@Override
public List<Proxy> select(URI uri) {
return Collections.singletonList(proxy);
}
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
System.err.println("Connection to " + uri + " failed: " + ioe.getMessage());
}
static class ProxyAuthenticator extends Authenticator {
private final String username;
private final String password;
public ProxyAuthenticator(String username, String password) {
this.username = username;
this.password = password;
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
}
}
参考文章
本文由作者按照 CC BY 4.0 进行授权