tis icon indicating copy to clipboard operation
tis copied to clipboard

为TIS设置内网代理功能

Open baisui1981 opened this issue 8 months ago • 1 comments

当用户把TIS部署在公司内网环境无法连接到TIS plugin仓库,此时可以使用公司其内网集群中开一个代理节点访问TIS的仓库,那么就需要在TIS上有设置代理节点的功能。

public class UpdateCenterResource {

    private static final MessageFormat UPDATE_CENTER_URL_FORMAT
            = new MessageFormat("http://mirror.qlangtech.com/{0}{1}/");
}

在 Java 中设置 HTTP 客户端使用代理的方法取决于你使用的具体 HTTP 客户端库。以下是几种常见库的代理设置示例:


1. Java 原生 HttpClient (JDK 11+)

import java.net.ProxySelector;
import java.net.http.HttpClient;
import java.net.URI;

// 设置代理
ProxySelector proxy = ProxySelector.of(
    new InetSocketAddress("代理IP", 代理端口) // 例如 127.0.0.1:8080
);

HttpClient client = HttpClient.newBuilder()
    .proxy(proxy) // 指定代理
    .build();

// 发送请求
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://example.com"))
    .build();

client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
    .thenApply(HttpResponse::body)
    .thenAccept(System.out::println);

2. Apache HttpClient 4.x/5.x

import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner;
import org.apache.hc.core5.http.HttpHost;

// 创建代理对象
HttpHost proxy = new HttpHost("http", "代理IP", 代理端口); // 例如 127.0.0.1:8080

// 设置代理路由
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
HttpClient client = HttpClientBuilder.create()
    .setRoutePlanner(routePlanner)
    .build();

// 发送请求(示例)
try (CloseableHttpResponse response = client.execute(new HttpGet("https://example.com"))) {
    // 处理响应
}

3. OkHttp

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.net.Proxy;

// 设置代理
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("代理IP", 代理端口));

OkHttpClient client = new OkHttpClient.Builder()
    .proxy(proxy) // 指定代理
    .build();

// 发送请求
Request request = new Request.Builder()
    .url("https://example.com")
    .build();

try (Response response = client.newCall(request).execute()) {
    System.out.println(response.body().string());
}

代理需要认证的情况

如果代理需要用户名和密码认证,需额外处理:

Apache HttpClient 5.x

import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;

BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
    new AuthScope("代理IP", 代理端口),
    new UsernamePasswordCredentials("用户名", "密码".toCharArray())
);

HttpClient client = HttpClientBuilder.create()
    .setRoutePlanner(routePlanner)
    .setDefaultCredentialsProvider(credsProvider)
    .build();

OkHttp

需自定义 Authenticator

client = new OkHttpClient.Builder()
    .proxy(proxy)
    .proxyAuthenticator((route, response) -> {
        String credential = Credentials.basic("用户名", "密码");
        return response.request().newBuilder()
            .header("Proxy-Authorization", credential)
            .build();
    })
    .build();

通过系统全局代理(适用于所有 HTTP 请求)

// 设置系统属性
System.setProperty("http.proxyHost", "代理IP");
System.setProperty("http.proxyPort", "代理端口");
System.setProperty("https.proxyHost", "代理IP");
System.setProperty("https.proxyPort", "代理端口");

// 如果代理需要认证
System.setProperty("jdk.http.auth.tunneling.disabledSchemes", ""); // 允许代理认证
Authenticator.setDefault(new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication("用户名", "密码".toCharArray());
    }
});

注意事项

  1. 代理类型:确保代理类型正确(HTTPSOCKS)。
  2. HTTPS:部分代理可能需要额外配置才能支持 HTTPS。
  3. 测试代理:建议先用 curl 或浏览器测试代理是否可用。

根据你使用的 HTTP 客户端库选择对应的配置方式即可。

baisui1981 avatar Mar 29 '25 01:03 baisui1981

以下是使用 java.net.URLHttpURLConnection 并通过代理发送请求的示例代码:

基础代理设置(无需认证)

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;

public class ProxyExample {
    public static void main(String[] args) {
        try {
            // 1. 定义代理服务器地址和端口
            String proxyHost = "127.0.0.1"; // 代理 IP
            int proxyPort = 8080;          // 代理端口
            
            // 2. 创建 Proxy 对象(HTTP 类型)
            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
            
            // 3. 创建 URL 对象并打开带代理的连接
            URL url = new URL("https://example.com");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
            
            // 4. 设置请求方法和其他属性
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000); // 5秒超时
            
            // 5. 读取响应
            int status = conn.getResponseCode();
            System.out.println("响应状态码: " + status);
            
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    System.out.println(line); // 输出响应内容
                }
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

如果代理需要认证

若代理需要用户名和密码,需通过 Authenticator 设置全局认证:

import java.net.Authenticator;
import java.net.PasswordAuthentication;

// 在代码开头添加认证配置
Authenticator.setDefault(new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        // 仅在代理认证时触发
        if (getRequestorType() == RequestorType.PROXY) {
            String proxyUser = "your_username";
            String proxyPass = "your_password";
            return new PasswordAuthentication(proxyUser, proxyPass.toCharArray());
        }
        return null;
    }
});

// 后续代码与基础示例相同

关键点说明

  1. 代理类型

    • Proxy.Type.HTTP:适用于 HTTP/HTTPS 代理
    • Proxy.Type.SOCKS:适用于 SOCKS 代理(需确保代理支持)
  2. 系统属性(可选): 若不想逐个连接设置代理,可通过系统属性全局配置:

    System.setProperty("http.proxyHost", "127.0.0.1");
    System.setProperty("http.proxyPort", "8080");
    System.setProperty("https.proxyHost", "127.0.0.1");
    System.setProperty("https.proxyPort", "8080");
    
  3. 异常处理

    • 捕获 IOException 处理网络错误
    • 处理 HTTP 407 状态码(代理认证失败)
  4. 关闭连接: 使用 try-with-resources 自动关闭流,避免资源泄漏。


验证代理是否生效

可以通过访问返回真实 IP 的测试网站(如 https://api.ipify.org)确认代理是否生效。

baisui1981 avatar Mar 29 '25 01:03 baisui1981

非常有用,急需,生产环境无外网

smartbin avatar Aug 29 '25 06:08 smartbin