Configurar proxies para aplicaciones Java usando HttpClient, Jsoup y Selenium implica configurar el host y el puerto del proxy, ya sea globalmente a través de las propiedades del sistema Java o específicamente para los objetos de conexión de cada biblioteca, a menudo incluyendo provisiones para la autenticación.
Fundamentos del Proxy en Java
Los servidores proxy actúan como intermediarios para las solicitudes de red, ofreciendo beneficios como seguridad mejorada, anonimato y acceso a contenido con restricciones geográficas. En Java, las configuraciones de proxy se pueden aplicar de forma general en la Máquina Virtual de Java (JVM) o específicamente a clientes HTTP individuales.
Tipos de Proxy
- Proxy HTTP: Maneja solicitudes HTTP (
http://). - Proxy HTTPS: Maneja solicitudes HTTPS (
https://). A menudo, un proxy HTTP también puede manejar solicitudes HTTPS a través del métodoCONNECT. - Proxy SOCKS: Soporta varios protocolos de red, no solo HTTP/HTTPS. Ofrece más flexibilidad y puede manejar tráfico TCP y UDP.
Autenticación de Proxy
Muchos proxies requieren autenticación (nombre de usuario/contraseña). Esto se puede manejar de manera diferente dependiendo de si el proxy está configurado globalmente o por cliente.
Configuración Global de Proxy (Propiedades del Sistema Java)
Java proporciona propiedades del sistema para configurar proxies que se aplican a todas las conexiones java.net, incluidas las realizadas por HttpURLConnection (que Jsoup usa internamente) y otras bibliotecas que por defecto utilizan estas configuraciones del sistema.
// Set HTTP proxy
System.setProperty("http.proxyHost", "proxy.example.com");
System.setProperty("http.proxyPort", "8080");
// Set HTTPS proxy (can be the same as HTTP or different)
System.setProperty("https.proxyHost", "proxy.example.com");
System.setProperty("https.proxyPort", "8080");
// Set SOCKS proxy
System.setProperty("socksProxyHost", "socks.example.com");
System.setProperty("socksProxyPort", "1080");
// Exclude hosts from proxying (comma-separated list, wildcards allowed)
System.setProperty("http.nonProxyHosts", "localhost|127.0.0.1|*.local");
Estas propiedades también se pueden pasar como argumentos de la JVM:
java -Dhttp.proxyHost=proxy.example.com -Dhttp.proxyPort=8080 YourApplication
Autenticación Global de Proxy
Para proxies que requieren autenticación, se puede usar la clase Authenticator de Java. Esto configura un autenticador predeterminado para todas las conexiones java.net.
import java.net.Authenticator;
import java.net.PasswordAuthentication;
public class GlobalProxyAuthenticator {
public static void setup(String username, String password) {
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
// Check if the request is for a proxy
if (getRequestorType() == RequestorType.PROXY) {
return new PasswordAuthentication(username, password.toCharArray());
}
return null; // No authentication for other requests
}
});
}
public static void main(String[] args) {
// Set global proxy properties
System.setProperty("http.proxyHost", "authenticated-proxy.example.com");
System.setProperty("http.proxyPort", "8080");
System.setProperty("https.proxyHost", "authenticated-proxy.example.com");
System.setProperty("https.proxyPort", "8080");
// Set up authenticator
GlobalProxyAuthenticator.setup("proxyuser", "proxypass");
// Now, any HttpURLConnection-based request will attempt to use this proxy and credentials
// Example: Jsoup will implicitly use this.
try {
org.jsoup.Connection.Response response = org.jsoup.Jsoup.connect("http://httpbin.org/get")
.ignoreContentType(true)
.execute();
System.out.println("Status: " + response.statusCode());
System.out.println("Body: " + response.body());
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
}
Apache HttpClient
Apache HttpClient proporciona métodos robustos y flexibles para realizar solicitudes HTTP y es ampliamente utilizado para integraciones complejas. Soporta configuración explícita de proxy por instancia de cliente.
HttpClient 4.x
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class HttpClient4ProxySetup {
public static void main(String[] args) throws Exception {
// 1. Define Proxy Host
HttpHost proxy = new HttpHost("proxy.example.com", 8080, "http"); // or "https" or "socks"
// 2. Configure Request with Proxy
RequestConfig config = RequestConfig.custom()
.setProxy(proxy)
.build();
// 3. (Optional) For Authenticated Proxy: Credentials Provider
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
new AuthScope(proxy.getHostName(), proxy.getPort()),
new UsernamePasswordCredentials("proxyuser", "proxypass"));
// 4. Build HttpClient
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(config)
.setDefaultCredentialsProvider(credentialsProvider) // For authenticated proxies
.build();
// 5. Execute Request
HttpGet request = new HttpGet("http://httpbin.org/get");
request.setConfig(config); // Ensure request uses the config
try (CloseableHttpResponse response = httpClient.execute(request)) {
System.out.println("Status: " + response.getStatusLine());
System.out.println("Body: " + EntityUtils.toString(response.getEntity()));
} finally {
httpClient.close();
}
}
}
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;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.ClassicHttpResponse;
public class HttpClient5ProxySetup {
public static void main(String[] args) throws Exception {
// 1. Define Proxy Host
HttpHost proxy = new HttpHost("http", "proxy.example.com", 8080); // Scheme, Host, Port
// 2. (Optional) For Authenticated Proxy: Credentials Provider
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
new AuthScope(proxy.getHostName(), proxy.getPort()),
new UsernamePasswordCredentials("proxyuser", "proxypass".toCharArray()));
// 3. Build HttpClient
CloseableHttpClient httpClient = HttpClients.custom()
.setProxy(proxy) // Set proxy directly on the client builder
.setDefaultCredentialsProvider(credentialsProvider) // For authenticated proxies
.build();
// 4. Execute Request
HttpGet request = new HttpGet("http://httpbin.org/get");
// RequestConfig can still be used for per-request overrides if needed
RequestConfig requestConfig = RequestConfig.custom()
// .setProxy(proxy) // Can also be set here for per-request proxy
.build();
request.setConfig(requestConfig);
try (CloseableHttpClient client = httpClient) {
client.execute(request, response -> {
System.out.println("Status: " + response.getCode());
System.out.println("Body: " + EntityUtils.toString(response.getEntity()));
return null;
});
}
}
}
Jsoup
Jsoup es una biblioteca Java para trabajar con HTML del mundo real. Proporciona una API simple para obtener URLs y analizar HTML. La interfaz Connection de Jsoup permite la configuración directa del proxy.
import org.jsoup.Jsoup;
import org.jsoup.Connection;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
public class JsoupProxySetup {
public static void main(String[] args) {
String url = "http://httpbin.org/get";
String proxyHost = "proxy.example.com";
int proxyPort = 8080;
try {
// Method 1: Using proxy(host, port)
Connection.Response response1 = Jsoup.connect(url)
.proxy(proxyHost, proxyPort)
.ignoreContentType(true)
.execute();
System.out.println("Jsoup (Method 1) Status: " + response1.statusCode());
System.out.println("Jsoup (Method 1) Body: " + response1.body().substring(0, 100) + "...\n");
// Method 2: Using java.net.Proxy object
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
Connection.Response response2 = Jsoup.connect(url)
.proxy(proxy)
.ignoreContentType(true)
.execute();
System.out.println("Jsoup (Method 2) Status: " + response2.statusCode());
System.out.println("Jsoup (Method 2) Body: " + response2.body().substring(0, 100) + "...\n");
} catch (IOException e) {
System.err.println("Error connecting via Jsoup proxy: " + e.getMessage());
e.printStackTrace();
}
// For authenticated proxies, Jsoup relies on global Java system properties and Authenticator.
// See "Global Proxy Setup" section for details.
}
}
Para proxies autenticados con Jsoup, el enfoque recomendado es configurar las propiedades globales del sistema Java y java.net.Authenticator como se demuestra en la sección "Configuración Global de Proxy". La HttpURLConnection interna de Jsoup tomará entonces estas configuraciones.
Selenium WebDriver
Selenium automatiza navegadores web. La configuración de proxy para Selenium WebDriver se realiza típicamente a través de opciones específicas del navegador.
Chrome WebDriver
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
public class SeleniumChromeProxySetup {
public static void main(String[] args) {
// Set path to ChromeDriver executable
// System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
String proxyHost = "proxy.example.com";
int proxyPort = 8080;
String proxyAddress = proxyHost + ":" + proxyPort;
Proxy proxy = new Proxy();
proxy.setHttpProxy(proxyAddress); // For HTTP traffic
proxy.setSslProxy(proxyAddress); // For HTTPS traffic (often same as HTTP)
proxy.setSocksProxy(proxyAddress); // For SOCKS traffic
// proxy.setSocksUsername("socksuser"); // For SOCKS5 authentication
// proxy.setSocksPassword("sockspass");
ChromeOptions options = new ChromeOptions();
options.setCapability("proxy", proxy);
// options.addArguments("--proxy-server=" + proxyAddress); // Alternative for simple HTTP/HTTPS proxy
WebDriver driver = new ChromeDriver(options);
try {
driver.get("http://httpbin.org/get");
System.out.println("Page title: " + driver.getTitle());
// Further interactions with the page...
} finally {
driver.quit();
}
}
}
Firefox WebDriver
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
public class SeleniumFirefoxProxySetup {
public static void main(String[] args) {
// Set path to GeckoDriver executable
// System.setProperty("webdriver.gecko.driver", "/path/to/geckodriver");
String proxyHost = "proxy.example.com";
int proxyPort = 8080;
String proxyAddress = proxyHost + ":" + proxyPort;
Proxy proxy = new Proxy();
proxy.setHttpProxy(proxyAddress);
proxy.setSslProxy(proxyAddress);
proxy.setSocksProxy(proxyAddress);
// proxy.setSocksUsername("socksuser");
// proxy.setSocksPassword("sockspass");
FirefoxOptions options = new FirefoxOptions();
options.setCapability("proxy", proxy);
WebDriver driver = new FirefoxDriver(options);
try {
driver.get("http://httpbin.org/get");
System.out.println("Page title: " + driver.getTitle());
} finally {
driver.quit();
}
}
}
Autenticación de Proxy en Selenium
Selenium WebDriver no maneja directamente la autenticación de proxy (nombre de usuario/contraseña para proxies HTTP/HTTPS). Los enfoques comunes incluyen:
- Extensiones de Navegador: Usar una extensión de navegador que maneje la autenticación de proxy. Estas extensiones se pueden cargar a través de
ChromeOptionsoFirefoxOptions. - Proxy en la URL: Para algunos proxies HTTP, las credenciales se pueden incrustar en la URL del proxy (por ejemplo,
user:pass@proxy.example.com:8080), pero esto no es universalmente compatible ni seguro. - Autenticación SOCKS5: La clase
Proxyde Selenium soportasetSocksUsername()ysetSocksPassword()para proxies SOCKS5. - Servidor Proxy Intermedio: Enrutar el tráfico a través de otro servidor proxy local (por ejemplo, BrowserMob Proxy) que gestione la autenticación con el proxy de destino.
Comparación de Métodos de Configuración de Proxy
| Característica | Propiedades del Sistema Java (-D) |
Apache HttpClient (4.x/5.x) | Jsoup (.proxy()) |
Selenium WebDriver (clase Proxy) |
|---|---|---|---|---|
| Alcance | Global (a nivel de JVM) | Por instancia de HttpClient |
Por instancia de Connection |
Por instancia de WebDriver |
| Autenticación | java.net.Authenticator (global) |
CredentialsProvider (por cliente) |
java.net.Authenticator (si es global) |
SOCKS5 (setSocksUsername/Password); HTTP/HTTPS típicamente a través de extensiones/herramientas externas |
| Flexibilidad | Baja (afecta todas las conexiones java.net) |
Alta (control granular, configuración por solicitud) | Moderada (por conexión, pero depende de la configuración global para la autenticación) | Alta (opciones específicas del navegador, autenticación SOCKS) |
| Facilidad de Uso | Alta (propiedades simples) | Moderada a Alta (requiere más código) | Alta (llamadas a métodos simples) | Moderada (requiere crear objeto Proxy y establecer opciones) |
| Protocolos Soportados | HTTP, HTTPS, SOCKS | HTTP, HTTPS, SOCKS | HTTP, HTTPS (a través de HttpURLConnection) |
HTTP, HTTPS, SOCKS (capacidades del navegador) |
| Casos de Uso | Necesidades de proxy simples y consistentes en la aplicación | Interacciones HTTP complejas, clientes de API | Web scraping, obtención simple de páginas | Automatización de navegador, pruebas, web scraping |