Работа с HTTP-контентом на HTTPS-страницах
У нас есть сайт, который доступен полностью по HTTPS, но иногда отображается внешний контент который является HTTP (изображения из RSS-каналов, в основном). Подавляющее большинство наших пользователей также застряли на IE6.
в идеале я хотел бы сделать оба из следующих
- предотвратите предупреждение IE о небезопасном контенте (чтобы я мог показать менее навязчивый, например, заменив изображения значком по умолчанию, как показано ниже)
- присутствует что-то полезное для пользователей вместо изображений, которые они не могут видеть иначе; если бы был какой-то JS, я мог бы запустить, чтобы выяснить, какие изображения не были загружены, и заменить их на наше изображение, вместо этого это было бы здорово.
Я подозреваю, что первая цель просто невозможна, но второй может быть достаточно.
худший сценарий заключается в том, что я разбираю RSS-каналы при их импорте, захватываю изображения, храните их локально, чтобы пользователи могли получить доступ они таким образом, но кажется, что много боли для разумно небольшой выгоды.
10 ответов:
ваш худший сценарий не так плох, как вы думаете.
вы уже анализируете RSS-канал, поэтому у вас уже есть URL-адреса изображений. Скажем, у вас есть URL-адрес изображения, например
http://otherdomain.com/someimage.jpg
. Вы переписываете этот URL какhttps://mydomain.com/imageserver?url=http://otherdomain.com/someimage.jpg&hash=abcdeafad
. Таким образом, браузер всегда делает запрос по https, так что вы избавитесь от проблем.следующая часть-создать прокси-страницу или сервлет, который делает следующее -
- прочитайте параметр url из строки запроса и проверьте хэш
- загрузить образ с сервера и прокси его обратно в браузер
- дополнительно, кэшировать изображение на диске
это решение имеет некоторые преимущества. Вам не нужно загружать изображение во время создания html. Вам не нужно хранить изображения локально. Кроме того, вы не имеете состояния; url-адрес содержит всю информацию, необходимую для обслуживания изображения.
наконец, параметр hash находится в безопасности, вы только хотите, чтобы ваши сервлет для обслуживания изображений для URL-адресов, которые вы создали. Итак, при создании url-адреса вычислите
md5(image_url + secret_key)
и добавьте его в качестве хэш-параметра. Прежде чем подавать запрос, пересчитайте хэш и сравните его с тем, что было передано вам. Поскольку secret_key известен только вам, никто другой не может построить допустимые URL-адреса.если вы разрабатываете на Java сервлет-это всего лишь несколько строк кода. Вы должны быть в состоянии портировать код на любой другой серверной технологии.
/* 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); } }
Если вы ищете быстрое решение для загрузки изображений по HTTPS, то БЕСПЛАТНЫЙ обратный прокси-сервис на https://images.weserv.nl/ может вас заинтересовать. Это было именно то, что я искал.
Если вы ищете платное решение, я ранее использовал Cloudinary.com что тоже хорошо работает, но слишком дорого исключительно для этой задачи, на мой взгляд.
Я не знаю, будет ли это соответствовать тому, что вы делаете, но в качестве быстрого решения я бы "обернул" содержимое http в скрипт https. Например, на Вашей странице, которая обслуживается через https, я бы представил iframe, который заменит ваш RSS-канал, а в src attr iframe поместите url-адрес сценария на ваш сервер, который захватывает канал и выводит html. скрипт читает фид через http и выводит его через https (таким образом, "обертывание")
просто мысли
Что касается вашего второго требования - вы можете использовать событие onerror, т. е.
<img onerror="some javascript;"...
обновление:
вы также можете попробовать перебора
document.images
в dom. Там естьcomplete
булево свойство, которое вы могли бы использовать. Я не знаю точно, будет ли это подходящим, но, возможно, стоит исследовать.
иногда, как в приложениях facebook, мы не можем иметь незащищенное содержимое на защищенной странице. также мы не можем сделать местное содержание. например, приложение, которое будет загружаться в iFrame, не является простым контентом, и мы не можем сделать его локальным.
Я думаю, что мы никогда не должны загружать содержимое http в https, также мы не должны возвращать https-страницу в http-версию, чтобы предотвратить диалоговое окно ошибки.
единственный способ, который обеспечит безопасность пользователя, - использовать https-версию всего содержимого, http://developers.facebook.com/blog/post/499/
принятый ответ помог мне обновить это как на PHP, так и на CORS, поэтому я подумал, что включу решение для других:
чистый PHP / HTML:
<?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.РНР смотрите http://stackoverflow.com/questions/8719276/cors-with-php-headers?noredirect=1&lq=1 подробнее о 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; }
просто: не делайте этого. Содержимое Http на странице HTTPS по своей сути небезопасно. Точка. Вот почему IE показывает предупреждение. Избавление от предупреждения-это глупый подход к фигне.
вместо этого страница HTTPS должна только есть содержимое HTTPS. Убедитесь, что содержимое также может быть загружено через HTTPS и ссылаться на него через https, если страница загружается через https. Для внешнего контента это будет означать загрузку и кэширование элементов локально, чтобы они были доступны через https - конечно. К сожалению, ничего не поделаешь.
предупреждение существует по уважительной причине. Серьезно. Потратьте 5 минут, думая, как вы могли бы взять на себя https показанную страницу с пользовательским контентом-вы будете удивлены.
лучший способ работы для меня
<img src="/path/image.png" />// this work only online or <img src="../../path/image.png" /> // this work both or asign variable <?php $base_url = ''; if($_SERVER['HTTP_HOST'] == 'localhost') { $base_url = 'localpath'; } ?> <img src="<?php echo $base_url;?>/path/image.png" />
Я понимаю, что это старый поток, но один из вариантов - просто удалить http: часть из URL-адреса изображения, чтобы'http://some/image.jpg "становится" //некоторые/изображения.jpg'. Это также будет работать с УСР