Telechargement fichier depuis url en https

Résolu/Fermé
jordane45 Messages postés 36604 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 7 décembre 2022 - 31 août 2016 à 11:20
Ibrahima.yi Messages postés 20 Date d'inscription lundi 21 mars 2016 Statut Membre Dernière intervention 19 mai 2017 - 17 oct. 2016 à 15:17
Bonjour,

J'essaye de télécharger un fichier depuis une url en https
https://machintruc.fr/bidule/monfichier.xls

NB: L'url a été modifiée depuis peu (n'était pas en https mais http tout court ) et le script fonctionnait parfaitement avant ce changement

Voici le code utilisé
private void getA()
    throws Exception
  {
    Utilitaire.afficherCommentaire("Recuperation de " + this.filenameA);
    System.setProperty("http.auth.ntlm.domain", domaine);
    
    System.out.println("URL=" + adresseA);
    URL url = new URL(adresseA);
    URLConnection uc = url.openConnection();
    int contentLength = uc.getContentLength();
    InputStream raw = uc.getInputStream();
    InputStream in = new BufferedInputStream(raw);
    byte[] data = new byte[contentLength];
    int bytesRead = 0;
    int offset = 0;
    while (offset < contentLength)
    {
      bytesRead = in.read(data, offset, data.length - offset);
      if (bytesRead == -1) {
        break;
      }
      offset += bytesRead;
    }
    in.close();
    if (offset != contentLength) {
      throw new IOException("Only read " + offset + " bytes; Expected " + contentLength + " bytes");
    }
    FileOutputStream out = new FileOutputStream(this.filenameA);
    out.write(data);
    out.flush();
    out.close();
  }
  



J'avais un Message d'erreur :
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target


J'ai donc suivi quelques docs sur le net indiquant qu'il suffisait d'installer le certificat du site dans le jdk/jre .... chose faite.
keytool -keystore cacerts -importcert -alias moncert -file d:\temp\moncert.cer


Mais maintenant... j'obtiens l'erreur : Server redirected too many times (20)


Auriez-vous, oh grands manitous du java..., une idée sur les causes du problème et un moyen d'y remédier ?


2 réponses

jordane45 Messages postés 36604 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 7 décembre 2022 4 420
31 août 2016 à 11:32
Bon ben j'ai trouvé....
mauvaise chaine de "login"..... j'avais oublié de doubler mes "\"
0
KX Messages postés 16643 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 6 décembre 2022 2 985
31 août 2016 à 15:49
12 minutes pour trouver ton problème tout seul, tu m'excuseras de ne pas être intervenu en temps utiles ^^

Remarque : plutôt que d'enregistrer le certificat du site dans le JDK (et donc de devoir le faire autant de fois qu'il y a de site à vérifier) il est plus intéressant d'enregistrer le certificat racine, afin d'autoriser tout les sites certifiés par cet organisme (s'il est fiable bien sûr).

Java connaît la plupart des autorités de certifications "standards" (VeriSign, GeoTrust, etc) ce qui couvre la plupart des sites https du web. Et régulièrement lors de mises à jours Java, de nouveaux certificats sont rajoutés.
Mais effectivement si le site est signé par un certificat maison... il faut le rajouter à la main.

On peut aussi (mais c'est plus moche) forcer Java à ignorer la vérification du certificat, un peu comme on peut le faire avec un navigateur web lorsque le https est "suspect".
0
jordane45 Messages postés 36604 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 7 décembre 2022 4 420 > KX Messages postés 16643 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 6 décembre 2022
31 août 2016 à 15:53
Hello ^^


12 minutes pour trouver ton problème tout seul, tu m'excuseras de ne pas être intervenu en temps utiles ^^

C'est 12 minutes fictives.... j'ai cherché une bonne parti de la soirée hier avant de me décider de poster ma question....
Et puis... (c'est souvent mon cas....) au moment de poster ma question... hop...un moment de lucidité.... :-)


il est plus intéressant d'enregistrer le certificat racine, afin d'autoriser tout les sites certifiés par cet organisme (s'il est fiable bien sûr).

C'est en effet ce que j'ai fait.


On peut aussi (mais c'est plus moche) forcer Java à ignorer la vérification du certificat, un peu comme on peut le faire avec un navigateur web lorsque le https est "suspect".

J'y avait pensé .. mais je n'ai pas trouvé (sans avoir trop cherché de toutes façons..) comment faire.
A la limite... si tu as cette technique sous la main.. ça m'interesse quand même....
0
KX Messages postés 16643 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 6 décembre 2022 2 985
31 août 2016 à 16:59
Déjà, je ne sais pas si c'est exactement lié mais il y a cette option globale :
https://java.com/en/download/help/revocation_options.html

Cependant, je pense que pour un utilisateur lambda, faire cette manipulation est un peu compliqué, il en va de même pour l'installation du certificat dans sa JRE.

Programmatiquement on peut ignorer la certification en faisant une surcharge des méthodes de vérification et faire en sorte qu'elles acceptent toujours tout.

Remarque : cette méthode permet également de renforcer la sécurité en analysant plus finement le contenu des certificats pour éventuellement rajouter des règles de contrôles supplémentaires (par exemple pour ne contourner la sécurité que pour une URL particulière).

Exemple :

package ccm;

import java.net.*;
import java.security.*;
import java.security.cert.*;
import java.util.*;
import javax.net.ssl.*;

class FakeTrustManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        System.out.println("# checkClientTrusted: " + authType);
        System.out.println(Arrays.toString(chain));
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        System.out.println("# checkServerTrusted: " + authType);
        System.out.println(Arrays.toString(chain));
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        System.out.println("# getAcceptedIssuers");
        return null;
    }
}

public class TestHttps {

    public static void disableSSL() {
        try {
            SSLContext ssl = SSLContext.getInstance("SSL");
            TrustManager[] tm = { new FakeTrustManager() };
            ssl.init(null, tm, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(ssl.getSocketFactory());
        } catch (RuntimeException | NoSuchAlgorithmException | KeyManagementException e) {
            throw new SecurityException("Can't disable SSL", e);
        }
    }

    public static void main(String[] args) throws Exception {
        disableSSL();
        Scanner sc = new Scanner(new URL("https://www.google.fr/").openStream());
        while (sc.hasNextLine()) {
            String line = sc.nextLine();
            // System.out.println(line);
        }
        sc.close();
    }
}

NB. j'ai pris https://www.google.fr comme exemple pour voir le contenu des certificats, en sachant que de toute façon Java accepte déjà le certificat de Google.
C'est à tester sur ton site récalcitrant ;-)
0
jordane45 Messages postés 36604 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 7 décembre 2022 4 420 > KX Messages postés 16643 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 6 décembre 2022
31 août 2016 à 17:07
Super.
Merci m'sieur. Je jetterai un oeil là dessus prochainement et te ferai un petit retour.
0