115 votes

La connexion HTTPURLC ne suit pas la redirection de HTTP à HTTPS

Je n'arrive pas à comprendre pourquoi le programme Java HttpURLConnection ne suit pas une redirection HTTP d'une URL HTTP vers une URL HTTPS. J'utilise le code suivant pour obtenir la page à 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();
        }
    }
}

La sortie de ce programme est :

Original URL: http://httpstat.us/301
Connected to: http://httpstat.us/301
HTTP response code received: 301
HTTP response message received: Moved Permanently

Une demande de http://httpstat.us/301 renvoie la réponse (abrégée) suivante (qui semble tout à fait correcte !):

HTTP/1.1 301 Moved Permanently
Cache-Control: private
Content-Length: 21
Content-Type: text/plain; charset=utf-8
Location: https://httpstat.us

Malheureusement, le système de Java HttpURLConnection ne suit pas la redirection !

Notez que si vous changez l'URL d'origine en HTTPS ( https://httpstat.us/301 ), Java sera suivre la redirection comme prévu ! ?

1 votes

Bonjour, j'ai modifié votre question pour plus de clarté et pour indiquer que la redirection vers HTTPS en particulier est le problème. De plus, j'ai changé le domaine bit.ly pour un autre, car l'utilisation de bit.ly est sur liste noire dans les questions. J'espère que cela ne vous dérange pas, n'hésitez pas à rééditer votre question.

136voto

erickson Points 127945

Les redirections ne sont suivies que si elles utilisent le même protocole. (Voir le site followRedirect() méthode dans la source). Il n'y a aucun moyen de désactiver cette vérification.

Même si nous savons qu'il reflète HTTP, du point de vue du protocole HTTP, HTTPS n'est qu'un autre protocole inconnu, complètement différent. Il serait dangereux de suivre la redirection sans l'accord de l'utilisateur.

Par exemple, supposons que l'application soit configurée pour effectuer automatiquement l'authentification du client. L'utilisateur s'attend à surfer anonymement parce qu'il utilise HTTP. Mais si son client suit HTTPS sans le demander, son identité est révélée au serveur.

65 votes

Merci. Je viens de trouver la confiramtion : bugs.sun.com/bugdatabase/view_bug.do?bug_id=4620571 . A savoir : "Après discussion entre les ingénieurs de Java Networking, il est estimé que nous ne devrions pas suivre automatiquement la redirection d'un protocole à un autre, par exemple, de http à https et vice versa, le faire peut avoir de graves conséquences sur la sécurité. La solution consiste donc à renvoyer les réponses du serveur pour la redirection. Vérifiez le code de réponse et la valeur du champ d'en-tête Location pour obtenir des informations sur la redirection. Il est de la responsabilité de l'application de suivre la redirection."

2 votes

Mais suit-il la redirection de http à http ou de https à https ? Même ça, ce serait faux. N'est-ce pas ?

0 votes

@Enigma Vous pouvez configurer ce comportement à l'échelle mondiale ou sur un par instance base. Par défaut, il fait suivre les redirections si le schéma ne change pas.

27voto

Jon Skeet Points 692016

Il y a quelque chose qui s'appelle HttpURLConnection.setFollowRedirects(false) par hasard ?

Vous pouvez toujours appeler

conn.setInstanceFollowRedirects(true);

si vous voulez être sûr de ne pas affecter le reste du comportement de l'application.

0 votes

Ooo... je ne connaissais pas ça... Belle découverte... J'étais sur le point de chercher la classe au cas où il y aurait une logique comme celle-là.... Il est logique qu'il serait retourner cet en-tête donnant la responsabilité unique principal.... maintenant revenir à répondre aux questions C # :P [Je plaisante]

2 votes

Notez que setFollowRedirects() doit être appelé sur la classe, et non sur une instance.

3 votes

@dldnh : Alors que karlbecker_com avait absolument raison d'appeler setFollowRedirects sur le type, setInstanceFollowRedirects est un instance et ne peut pas être appelé sur le type.

7voto

Shalvika Points 86

Comme mentionné par certains d'entre vous ci-dessus, le setFollowRedirect et le setInstanceFollowRedirects ne fonctionnent automatiquement que lorsque le protocole redirigé est le même, c'est-à-dire de http à http et de https à https.

setFolloRedirect est au niveau de la classe et définit ceci pour toutes les instances de la connexion url, alors que setInstanceFollowRedirects est seulement pour une instance donnée. De cette façon, nous pouvons avoir un comportement différent pour différentes instances.

J'ai trouvé un très bon exemple ici http://www.mkyong.com/java/java-httpurlconnection-follow-redirect-example/

0voto

sp. Points 702

C'est la réponse correcte, mais vous devez récupérer le nouvel emplacement de la réponse et l'utiliser comme url.

-5voto

monksy Points 8788

HTTPUrlConnection n'est pas responsable de la gestion de la réponse de l'objet. Elle fonctionne comme prévu, elle saisit le contenu de l'URL demandée. C'est à vous, l'utilisateur de la fonctionnalité, d'interpréter la réponse. Il n'est pas en mesure de lire les intentions du développeur sans spécification.

8 votes

Pourquoi y a-t-il setInstanceFollowRedirects dans ce cas ? ))

0 votes

Je pense qu'il s'agissait d'une fonctionnalité suggérée à ajouter plus tard, c'est logique... mon commentaire était plus une réflexion vers... la classe est conçue pour aller chercher du contenu web et le ramener... les gens peuvent vouloir obtenir des messages non HTTP 200.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X