web-dev-qa-db-fra.com

Traitement du contenu HTTP dans les pages HTTPS

Nous avons un site qui est entièrement accessible via HTTPS, mais affiche parfois contenu externe qui est HTTP (images provenant principalement de flux RSS). La grande majorité de nos utilisateurs sont également bloqués sur IE6.

J'aimerais idéalement faire les deux choses suivantes

  • Empêcher le message d'avertissement IE concernant le contenu non sécurisé (afin que je puisse en afficher un moins intrusif, par exemple en remplaçant les images par une icône par défaut, comme indiqué ci-dessous)
  • Présentez aux utilisateurs quelque chose d’utile à la place des images qu’ils ne pourraient pas voir autrement; S'il y avait un JS, je pourrais trouver les images qui n'ont pas été chargées et les remplacer par une de nos images, ce qui serait formidable.

Je soupçonne que le premier objectif n'est tout simplement pas possible, mais le second peut suffire.

Le pire des scénarios est d'analyser les flux RSS lors de leur importation, de récupérer les images stockées localement afin que les utilisateurs puissent y accéder de cette façon, mais cela semble très pénible pour un gain relativement modeste.

86
El Yobo

Votre pire scénario n'est pas aussi grave que vous le pensez.

Vous analysez déjà le flux RSS, vous avez donc déjà les URL de l'image. Supposons que vous ayez une URL d'image telle que http://otherdomain.com/someimage.jpg. Vous réécrivez cette URL en tant que https://mydomain.com/imageserver?url=http://otherdomain.com/someimage.jpg&hash=abcdeafad. De cette façon, le navigateur fait toujours une demande via https, ce qui vous permet d'éliminer les problèmes.

La partie suivante - créez une page de proxy ou un servlet qui effectue les opérations suivantes - 

  1. Lire le paramètre url de la chaîne de requête et vérifier le hachage
  2. Téléchargez l'image du serveur et envoyez-la par proxy au navigateur.
  3. Cachez éventuellement l'image sur le disque

Cette solution présente des avantages. Il n'est pas nécessaire de télécharger l'image au moment de la création du code HTML. Vous n'êtes pas obligé de stocker les images localement. De plus, vous êtes apatride; L'URL contient toutes les informations nécessaires pour servir l'image. 

Enfin, le paramètre de hachage est pour la sécurité; vous voulez que votre servlet ne serve les images que pour les URL que vous avez construites. Ainsi, lorsque vous créez l'URL, calculez md5(image_url + secret_key) et ajoutez-le en tant que paramètre de hachage. Avant de servir la demande, recalculez le hachage et comparez-le à ce qui vous a été transmis. Comme vous ne connaissez que la secret_key, personne d'autre ne peut construire d'URL valides.

Si vous développez en Java, le Servlet ne contient que quelques lignes de code. Vous devriez pouvoir porter le code ci-dessous sur toute autre technologie dorsale.

/*
targetURL is the url you get from RSS feeds
request and response are wrt to the browser
Assumes you have commons-io in your classpath
*/

protected void proxyResponse (String targetURL, HttpServletRequest request,
 HttpServletResponse response) throws IOException {
    GetMethod get = new GetMethod(targetURL);
    get.setFollowRedirects(true);    
    /*
     * Proxy the request headers from the browser to the target server
     */
    Enumeration headers = request.getHeaderNames();
    while(headers!=null && headers.hasMoreElements())
    {
        String headerName = (String)headers.nextElement();

        String headerValue = request.getHeader(headerName);

        if(headerValue != null)
        {
            get.addRequestHeader(headerName, headerValue);
        }            
    }        

    /*Make a request to the target server*/
    m_httpClient.executeMethod(get);
    /*
     * Set the status code
     */
    response.setStatus(get.getStatusCode());

    /*
     * proxy the response headers to the browser
     */
    Header responseHeaders[] = get.getResponseHeaders();
    for(int i=0; i<responseHeaders.length; i++)
    {
        String headerName = responseHeaders[i].getName();
        String headerValue = responseHeaders[i].getValue();

        if(headerValue != null)
        {
            response.addHeader(headerName, headerValue);
        }
    }

    /*
     * Proxy the response body to the browser
     */
    InputStream in = get.getResponseBodyAsStream();
    OutputStream out = response.getOutputStream();

    /*
     * If the server sends a 204 not-modified response, the InputStream will be null.
     */
    if (in !=null) {
        IOUtils.copy(in, out);
    }    
}
145
Sripathi Krishnan

Si vous recherchez une solution rapide pour charger des images via HTTPS, le service gratuit de proxy inverse de https://images.weserv.nl/ peut vous intéresser. C'était exactement ce que je cherchais. 

Si vous cherchez une solution payante, j’ai déjà utilisé Cloudinary.com, qui fonctionne également bien mais qui est trop cher uniquement pour cette tâche, à mon avis.

11
nullable

Je ne sais pas si cela conviendrait à ce que vous faites, mais comme solution rapide, je voudrais "envelopper" le contenu http dans un script https. Par exemple, sur votre page qui est servie via https, je voudrais introduire un iframe qui remplacerait votre flux rss. Dans le src attr de l'iframe, mettez une URL d'un script sur votre serveur qui capture le flux et génère le code HTML. le script lit le flux via http et le renvoie via https (donc "wrapping")

Juste une pensée

3
Raine

En ce qui concerne votre deuxième exigence - vous pourrez peut-être utiliser l’événement onerror, c.-à-d. <img onerror="some javascript;"...

Mettre à jour:

Vous pouvez également essayer de parcourir document.images dans le domaine. Il est possible d'utiliser une propriété booléenne complete. Je ne sais pas avec certitude si cela conviendra, mais cela vaut peut-être la peine d’enquêter.

2
UpTheCreek

Il serait préférable d’avoir le contenu http sur https

0
Daniel

La réponse acceptée m'a aidée à mettre à jour cette mise à jour vers PHP et CORS, alors j'ai pensé inclure la solution pour les autres:

pHP/HTML pur:

<?php // (the originating page, where you want to show the image)
// set your image location in whatever manner you need
$imageLocation = "http://example.com/exampleImage.png";

// set the location of your 'imageserve' program
$imageserveLocation = "https://example.com/imageserve.php";

// we'll look at the imageLocation and if it is already https, don't do anything, but if it is http, then run it through imageserve.php
$imageURL = (strstr("https://",$imageLocation)?"": $imageserveLocation . "?image=") . $imageLocation;

?>
<!-- this is the HTML image -->
<img src="<?php echo $imageURL ?>" />

javascript/jQuery:

<img id="theImage" src="" />
<script>
    var imageLocation = "http://example.com/exampleImage.png";
    var imageserveLocation = "https://example.com/imageserve.php";
    var imageURL = ((imageLocation.indexOf("https://") !== -1) ? "" : imageserveLocation + "?image=") + imageLocation;
    // I'm using jQuery, but you can use just javascript...        
    $("#theImage").prop('src',imageURL);
</script>

imageserve.php voir http://stackoverflow.com/questions/8719276/cors-with-php-headers?noredirect=1&lq=1 pour plus d'informations sur CORS

<?php
// set your secure site URL here (where you are showing the images)
$mySecureSite = "https://example.com";

// here, you can set what kinds of images you will accept
$supported_images = array('png','jpeg','jpg','gif','ico');

// this is an ultra-minimal CORS - sending trusted data to yourself 
header("Access-Control-Allow-Origin: $mySecureSite");

$parts = pathinfo($_GET['image']);
$extension = $parts['extension'];
if(in_array($extension,$supported_images)) {
    header("Content-Type: image/$extension");
    $image = file_get_contents($_GET['image']);
    echo $image;
}
0
CFP Support

Parfois, comme dans les applications Facebook, nous ne pouvons pas avoir de contenu non sécurisé dans une page sécurisée. Nous ne pouvons pas non plus rendre ces contenus locaux. Par exemple, une application qui se chargera dans iFrame n’est pas un contenu simple et nous ne pouvons pas la rendre locale.

Je pense que nous ne devrions jamais charger le contenu http dans https, nous ne devrions pas non plus ramener la page https à la version http pour éviter le dialogue d'erreur.

le seul moyen d'assurer la sécurité de l'utilisateur consiste à utiliser la version https de tout le contenu, http://developers.facebook.com/blog/post/499/

0