Я не могу понять, почему Java HttpURLConnection
не выполняет перенаправление HTTP с HTTP на URL-адрес HTTPS. Я использую следующий код для получения страницы по адресу https://httpstat.us/ :
import java.net.URL;
import java.net.HttpURLConnection;
import java.io.InputStream;
public class Tester {
public static void main(String argv[]) throws Exception{
InputStream is = null;
try {
String httpUrl = "http://httpstat.us/301";
URL resourceUrl = new URL(httpUrl);
HttpURLConnection conn = (HttpURLConnection)resourceUrl.openConnection();
conn.setConnectTimeout(15000);
conn.setReadTimeout(15000);
conn.connect();
is = conn.getInputStream();
System.out.println("Original URL: "+httpUrl);
System.out.println("Connected to: "+conn.getURL());
System.out.println("HTTP response code received: "+conn.getResponseCode());
System.out.println("HTTP response message received: "+conn.getResponseMessage());
} finally {
if (is != null) is.close();
}
}
}
Результат этой программы:
Исходный URL: http://httpstat.us/301 Подключено к: http://httpstat.us/301 Получен код ответа HTTP: 301 Получено ответное сообщение HTTP: перемещено навсегда
Запрос на http://httpstat.us/301 возвращает следующий (сокращенный) ответ (что кажется абсолютно правильным!):
HTTP/1.1 301 Moved Permanently
Cache-Control: private
Content-Length: 21
Content-Type: text/plain; charset=utf-8
Location: https://httpstat.us
К сожалению, Java HttpURLConnection
не выполняет перенаправление!
Обратите внимание, что если вы измените исходный URL-адрес на HTTPS ( https://httpstat.us/301 ), Java будет следовать за перенаправлением, как ожидалось !?
Ответы:
Перенаправления выполняются, только если они используют один и тот же протокол. (См на
followRedirect()
метод в источнике) . Там нет никакого способа , чтобы отключить эту проверку.Несмотря на то, что мы знаем, что он отражает HTTP, с точки зрения протокола HTTP, HTTPS - это просто другой, совершенно другой, неизвестный протокол. Было бы небезопасно выполнять перенаправление без одобрения пользователя.
Например, предположим, что приложение настроено для автоматического выполнения аутентификации клиента. Пользователь ожидает анонимного серфинга, потому что он использует HTTP. Но если его клиент следует HTTPS, не спрашивая, его личность раскрывается серверу.
источник
HttpURLConnection
не будет автоматически выполнять перенаправления на другой протокол, даже если установлен флаг перенаправления.HttpURLConnection по дизайну не будут автоматически перенаправлять от HTTP к HTTPS (или наоборот). Выполнение перенаправления может иметь серьезные последствия для безопасности. SSL (следовательно, HTTPS) создает сеанс, уникальный для пользователя. Этот сеанс можно повторно использовать для нескольких запросов. Таким образом, сервер может отслеживать все запросы от одного человека. Это слабая форма идентичности, и ее можно использовать. Кроме того, рукопожатие SSL может запросить сертификат клиента. При отправке на сервер личность клиента передается серверу.
Как указывает Эриксон , предположим, что приложение настроено для автоматической аутентификации клиента. Пользователь ожидает, что будет просматривать страницы анонимно, потому что он использует HTTP. Но если его клиент следует HTTPS, не спрашивая, его личность раскрывается серверу.
Программист должен предпринять дополнительные шаги, чтобы гарантировать, что учетные данные, сертификаты клиента или идентификатор сеанса SSL не будут отправлены перед перенаправлением с HTTP на HTTPS. По умолчанию они отправляются. Если перенаправление причиняет вред пользователю, не выполняйте перенаправление. Вот почему автоматическое перенаправление не поддерживается.
С учетом этого, вот код, который будет следовать за перенаправлениями.
источник
location = URLDecoder.decode(location...
. Это декодирует рабочую закодированную относительную часть (в моем случае с пробелом = +) в нерабочую. После того, как я его удалил, меня все устроило.Что-то
HttpURLConnection.setFollowRedirects(false)
случайно позвонило ?Вы всегда могли позвонить
если вы хотите убедиться, что не повлияете на остальное поведение приложения.
источник
setFollowRedirects
типа,setInstanceFollowRedirects
это метод экземпляра и не может быть вызван для типа.Как упоминалось некоторыми из вас выше, setFollowRedirect и setInstanceFollowRedirects работают автоматически только при одинаковом перенаправленном протоколе. т.е. с http на http и https на https.
setFolloRedirect находится на уровне класса и устанавливает это для всех экземпляров URL-соединения, тогда как setInstanceFollowRedirects только для данного экземпляра. Таким образом, у нас может быть разное поведение для разных экземпляров.
Я нашел здесь очень хороший пример http://www.mkyong.com/java/java-httpurlconnection-follow-redirect-example/
источник
Другой вариант - использовать клиент Apache HttpComponents :
Образец кода:
источник
HTTPUrlConnection не отвечает за обработку ответа объекта. Это ожидаемая производительность, он захватывает содержимое запрошенного URL-адреса. Вы, как пользователь функциональности, должны интерпретировать ответ. Он не может прочитать намерения разработчика без уточнения.
источник