HTTP-прокси с аутентификацией и Java
Как я могу настроить имя пользователя и пароль для аутентификации прокси-сервера http с использованием Java?
Я только что нашел следующие параметры конфигурации:
http.proxyHost=<proxyAddress>
http.proxyPort=<proxyPort>
https.proxyHost=<proxyAddress>
https.proxyPort=<proxyPort>
Но мой прокси-сервер требует аутентификации. Как я могу настроить свое приложение на использование прокси-сервера?
8 ответов
(РЕДАКТИРОВАТЬ: Как указано OP, использование java.net.Authenticator
тоже требуется. Я корректирую свой ответ соответственно для корректности.)
Для аутентификации используйте java.net.Authenticator
установить конфигурацию прокси и установить системные свойства http.proxyUser
а также http.proxyPassword
,
final String authUser = "user";
final String authPassword = "password";
Authenticator.setDefault(
new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
authUser, authPassword.toCharArray());
}
}
);
System.setProperty("http.proxyUser", authUser);
System.setProperty("http.proxyPassword", authPassword);
Вы почти у цели, вам просто нужно добавить:
-Dhttp.proxyUser=someUserName
-Dhttp.proxyPassword=somePassword
http://rolandtapken.de/blog/2012-04/java-process-httpproxyuser-and-httpproxypassword говорит:
Другие предлагают использовать собственный Аутентификатор по умолчанию. Но это опасно, потому что это отправит ваш пароль любому, кто попросит.
Это актуально, если некоторые запросы http / https не проходят через прокси (что вполне возможно в зависимости от конфигурации). В этом случае вы отправите свои учетные данные напрямую на какой-либо http-сервер, а не на свой прокси-сервер.
Он предлагает следующее исправление.
// Java ignores http.proxyUser. Here come's the workaround.
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
if (getRequestorType() == RequestorType.PROXY) {
String prot = getRequestingProtocol().toLowerCase();
String host = System.getProperty(prot + ".proxyHost", "");
String port = System.getProperty(prot + ".proxyPort", "80");
String user = System.getProperty(prot + ".proxyUser", "");
String password = System.getProperty(prot + ".proxyPassword", "");
if (getRequestingHost().equalsIgnoreCase(host)) {
if (Integer.parseInt(port) == getRequestingPort()) {
// Seems to be OK.
return new PasswordAuthentication(user, password.toCharArray());
}
}
}
return null;
}
});
Я еще не пробовал, но это выглядит хорошо для меня.
Из-за этого я немного изменил исходную версию, чтобы использовать equalsIgnoreCase() вместо equals(host.toLowerCase()): http://mattryall.net/blog/2009/02/the-infamous-turkish-locale-bug и я. добавлено "80" в качестве значения по умолчанию для порта, чтобы избежать NumberFormatException в Integer.parseInt(порт).
Большая часть ответа есть, но для меня не совсем. Это то, что работает для меня с java.net.HttpURLConnection (я проверил все случаи с JDK 7 и JDK 8). Обратите внимание, что вам не нужно использовать класс Authenticator.
Случай 1: Прокси без аутентификации пользователя, доступ к ресурсам HTTP
-Dhttp.proxyHost=myproxy -Dhttp.proxyPort=myport
Случай 2: Прокси с аутентификацией пользователя, доступ к ресурсам HTTP
-Dhttp.proxyHost=myproxy -Dhttp.proxyPort=myport -Dhttps.proxyUser=myuser -Dhttps.proxyPassword=mypass
Случай 3: Прокси без аутентификации пользователя, доступ к ресурсам HTTPS (SSL)
-Dhttps.proxyHost=myproxy -Dhttps.proxyPort=myport
Случай 4: Прокси с аутентификацией пользователя, доступ к ресурсам HTTPS (SSL)
-Dhttps.proxyHost=myproxy -Dhttps.proxyPort=myport -Dhttps.proxyUser=myuser -Dhttps.proxyPassword=mypass
Случай 5: Прокси-сервер без аутентификации пользователя, доступ к ресурсам HTTP и HTTPS (SSL)
-Dhttp.proxyHost=myproxy -Dhttp.proxyPort=myport -Dhttps.proxyHost=myproxy -Dhttps.proxyPort=myport
Случай 6: Прокси с аутентификацией пользователя, доступ к ресурсам HTTP и HTTPS (SSL)
-Dhttp.proxyHost=myproxy -Dhttp.proxyPort=myport -Dhttp.proxyUser=myuser -Dhttp.proxyPassword=mypass -Dhttps.proxyHost=myproxy -Dhttps.proxyPort=myport -Dhttps.proxyUser=myuser -Dhttps.proxyPassword=mypass
Вы также можете установить свойства в с помощью System.setProperty("ключ", "значение").
Чтобы получить доступ к HTTPS-ресурсу, вам, возможно, придется довериться ресурсу, загрузив сертификат сервера и сохранив его в хранилище доверенных сертификатов, а затем используя это хранилище доверенных сертификатов. т.е.
System.setProperty("javax.net.ssl.trustStore", "c:/temp/cert-factory/my-cacerts");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
Для Java 1.8 и выше вы должны установить
-Djdk.http.auth.tunneling.disabledSchemes=
сделать прокси с Базовой Авторизацией, работающей с https вместе с Аутентификатором, как указано в принятом ответе
Но, устанавливая только эти параметры, аутентификация не работает.
К этому коду необходимо добавить следующее:
final String authUser = "myuser";
final String authPassword = "secret";
System.setProperty("http.proxyHost", "hostAddress");
System.setProperty("http.proxyPort", "portNumber");
System.setProperty("http.proxyUser", authUser);
System.setProperty("http.proxyPassword", authPassword);
Authenticator.setDefault(
new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(authUser, authPassword.toCharArray());
}
}
);
Попробуйте этот раннер, который я написал. Это может быть полезно.
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.net.URLConnection;
import java.util.Scanner;
public class ProxyAuthHelper {
public static void main(String[] args) throws Exception {
String tmp = System.getProperty("http.proxyUser", System.getProperty("https.proxyUser"));
if (tmp == null) {
System.out.println("Proxy username: ");
tmp = new Scanner(System.in).nextLine();
}
final String userName = tmp;
tmp = System.getProperty("http.proxyPassword", System.getProperty("https.proxyPassword"));
if (tmp == null) {
System.out.println("Proxy password: ");
tmp = new Scanner(System.in).nextLine();
}
final char[] password = tmp.toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
System.out.println("\n--------------\nProxy auth: " + userName);
return new PasswordAuthentication (userName, password);
}
});
Class<?> clazz = Class.forName(args[0]);
Method method = clazz.getMethod("main", String[].class);
String[] newArgs = new String[args.length - 1];
System.arraycopy(args, 1, newArgs, 0, newArgs.length);
method.invoke(null, new Object[]{newArgs});
}
}
Поскольку никто не упомянул об этом, и я видел несколько примеров, когда
import java.net.*;
import java.util.Base64;
class JavaFileUtil {
private String hostname = "hostname";
private int port = 8000;
private String username = "username";
private String password = "password";
private Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(hostname, port));
private String authHeader = new String(Base64.getEncoder().encode(new String(username + ":" + password).getBytes()));
public void download(URL url) {
HttpURLConnection newConnection = null;
try {
newConnection = (HttpURLConnection) url.openConnection(proxy);
newConnection.setRequestProperty("Proxy-Authorization", "Basic " + authHeader);
//The rest of your code here
} catch (Exception e) {
//log some error or handle it
} finally {
//Make sure you close the connection
if (newConnection != null) newConnection.disconnect();
}
}
}