Me gustaría proporcionar una respuesta para el caso de que no tenga control sobre el código que abre la conexión. Como lo hice al usar el URLClassLoader
para cargar un archivo jar desde un servidor protegido con contraseña.
La Authenticator
solución funcionaría, pero tiene el inconveniente de que primero intenta llegar al servidor sin una contraseña y solo después de que el servidor solicite una contraseña. Es un viaje de ida y vuelta innecesario si ya sabe que el servidor necesitaría una contraseña.
public class MyStreamHandlerFactory implements URLStreamHandlerFactory {
private final ServerInfo serverInfo;
public MyStreamHandlerFactory(ServerInfo serverInfo) {
this.serverInfo = serverInfo;
}
@Override
public URLStreamHandler createURLStreamHandler(String protocol) {
switch (protocol) {
case "my":
return new MyStreamHandler(serverInfo);
default:
return null;
}
}
}
public class MyStreamHandler extends URLStreamHandler {
private final String encodedCredentials;
public MyStreamHandler(ServerInfo serverInfo) {
String strCredentials = serverInfo.getUsername() + ":" + serverInfo.getPassword();
this.encodedCredentials = Base64.getEncoder().encodeToString(strCredentials.getBytes());
}
@Override
protected URLConnection openConnection(URL url) throws IOException {
String authority = url.getAuthority();
String protocol = "http";
URL directUrl = new URL(protocol, url.getHost(), url.getPort(), url.getFile());
HttpURLConnection connection = (HttpURLConnection) directUrl.openConnection();
connection.setRequestProperty("Authorization", "Basic " + encodedCredentials);
return connection;
}
}
Esto registra un nuevo protocolo my
que se reemplaza http
cuando se agregan las credenciales. Entonces, al crear el nuevo URLClassLoader
solo reemplace http
con my
y todo está bien. Sé que URLClassLoader
proporciona un constructor que toma un URLStreamHandlerFactory
pero esta fábrica no se usa si la URL apunta a un archivo jar.