Não consigo entender por que o Java HttpURLConnection
não segue um redirecionamento HTTP de um URL HTTP para um HTTPS. Eu uso o seguinte código para obter a página em 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();
}
}
}
O resultado deste programa é:
URL original: http://httpstat.us/301 Conectado a: http://httpstat.us/301 Código de resposta HTTP recebido: 301 Mensagem de resposta HTTP recebida: movida permanentemente
Uma solicitação para http://httpstat.us/301 retorna a seguinte resposta (abreviada) (que parece absolutamente correta!):
HTTP/1.1 301 Moved Permanently
Cache-Control: private
Content-Length: 21
Content-Type: text/plain; charset=utf-8
Location: https://httpstat.us
Infelizmente, o Java HttpURLConnection
não segue o redirecionamento!
Note que se você alterar a URL original para HTTPS ( https://httpstat.us/301 ), Java vai seguir o redirecionamento como esperado !?
java
redirect
https
httpurlconnection
http-redirect
Shcheklein
fonte
fonte
Respostas:
Os redirecionamentos são seguidos apenas se usarem o mesmo protocolo. (Consulte o
followRedirect()
método na fonte.) Não há como desativar essa verificação.Mesmo sabendo que ele espelha o HTTP, do ponto de vista do protocolo HTTP, o HTTPS é apenas algum outro protocolo desconhecido completamente diferente. Não seria seguro seguir o redirecionamento sem a aprovação do usuário.
Por exemplo, suponha que o aplicativo esteja configurado para executar a autenticação do cliente automaticamente. O usuário espera navegar anonimamente porque está usando HTTP. Mas se seu cliente seguir HTTPS sem perguntar, sua identidade é revelada ao servidor.
fonte
HttpURLConnection
não seguirá automaticamente os redirecionamentos para um protocolo diferente, mesmo se o sinalizador de redirecionamento estiver definido.HttpURLConnection por design não redirecionará automaticamente de HTTP para HTTPS (ou vice-versa). Seguir o redirecionamento pode ter consequências graves para a segurança. SSL (portanto, HTTPS) cria uma sessão exclusiva para o usuário. Esta sessão pode ser reutilizada para várias solicitações. Assim, o servidor pode rastrear todas as solicitações feitas de uma única pessoa. Esta é uma forma fraca de identidade e pode ser explorada. Além disso, o handshake SSL pode solicitar o certificado do cliente. Se enviado ao servidor, a identidade do cliente é fornecida ao servidor.
Como erickson aponta, suponha que o aplicativo esteja configurado para executar a autenticação do cliente automaticamente. O usuário espera navegar anonimamente porque está usando HTTP. Mas se seu cliente seguir HTTPS sem perguntar, sua identidade é revelada ao servidor.
O programador deve tomar medidas extras para garantir que credenciais, certificados de cliente ou id de sessão SSL não sejam enviados antes de redirecionar de HTTP para HTTPS. O padrão é enviá-los. Se o redirecionamento prejudicar o usuário, não siga o redirecionamento. É por isso que o redirecionamento automático não é compatível.
Com isso entendido, aqui está o código que seguirá os redirecionamentos.
fonte
location = URLDecoder.decode(location...
parte. Isso decodifica uma parte relativa codificada funcional (com espaço = + no meu caso) em uma não funcional. Depois de removê-lo, estava tudo bem para mim.Alguma coisa ligou
HttpURLConnection.setFollowRedirects(false)
por acaso?Você sempre pode ligar
se você quiser ter certeza de que não afetará o resto do comportamento do aplicativo.
fonte
setFollowRedirects
o tipo,setInstanceFollowRedirects
é um método de instância e não pode ser chamado no tipo.Conforme mencionado por alguns de vocês acima, setFollowRedirect e setInstanceFollowRedirects só funcionam automaticamente quando o protocolo redirecionado é o mesmo. ou seja, de http para http e https para https.
setFolloRedirect está no nível de classe e define isso para todas as instâncias da conexão url, enquanto setInstanceFollowRedirects é apenas para uma determinada instância. Dessa forma, podemos ter comportamentos diferentes para instâncias diferentes.
Encontrei um exemplo muito bom aqui http://www.mkyong.com/java/java-httpurlconnection-follow-redirect-example/
fonte
Outra opção pode ser usar o cliente Apache HttpComponents :
Código de amostra:
fonte
HTTPUrlConnection não é responsável por manipular a resposta do objeto. É o desempenho esperado, ele pega o conteúdo da URL solicitada. Cabe a você, usuário da funcionalidade, interpretar a resposta. Não é capaz de ler as intenções do desenvolvedor sem especificação.
fonte