我们有一个完全通过HTTPS访问的网站,但有时会显示外部内容,即HTTP(主要来自RSS Feed的图片)。绝大多数用户也被困在IE6上。
我最好还是喜欢以下两个
我怀疑第一个目标根本不可能,但第二个目标可能就足够了。
最糟糕的情况是我在导入时解析RSS源,抓取图像将它们存储在本地,以便用户可以通过这种方式访问它们,但似乎很难获得相当大的收益。
答案 0 :(得分:146)
你最糟糕的情况并不像你想象的那么糟糕。
您已在解析RSS Feed,因此您已拥有图片网址。假设您有一个像http://otherdomain.com/someimage.jpg
这样的图片网址。您将此URL重写为https://mydomain.com/imageserver?url=http://otherdomain.com/someimage.jpg&hash=abcdeafad
。这样,浏览器总是通过https发出请求,因此您可以解决问题。
下一部分 - 创建执行以下操作的代理页面或servlet -
这种解决方案有一些优点。您不必在创建html时下载图像。您不必在本地存储图像。而且,你是无国籍的; url包含提供图像所需的所有信息。
最后,hash参数用于安全性;您只希望您的servlet为您构建的URL提供图像。因此,在创建URL时,请计算md5(image_url + secret_key)
并将其作为哈希参数附加。在您提供请求之前,请重新计算哈希值并将其与传递给您的哈希值进行比较。由于secret_key只为您所知,因此没有其他人可以构建有效的URL。
如果您使用java进行开发,Servlet只需几行代码。您应该能够在任何其他后端技术上移植以下代码。
/*
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);
}
}
答案 1 :(得分:12)
如果您正在寻找通过HTTPS加载图片的快速解决方案,那么https://images.weserv.nl/的免费反向代理服务可能会让您感兴趣。这正是我想要的。
如果您正在寻找付费解决方案,我之前使用的Cloudinary.com也运行良好,但在我看来,这个任务太贵了。
答案 2 :(得分:3)
我不知道这是否符合您的要求,但作为快速修复,我会将http内容“包装”到https脚本中。例如,在通过https提供的页面上,我将引入一个iframe来替换你的RSS提要,并在iframe的src attr中放置一个脚本,在你的服务器上捕获feed并输出html。脚本通过http读取feed并通过https输出(因此“包装”)
只是一个想法
答案 3 :(得分:2)
关于你的第二个要求 - 你可能能够利用onerror事件,即。 <img onerror="some javascript;"...
更新
你也可以尝试在dom中迭代document.images
。您可以使用complete
布尔属性。我不确定这是否合适,但可能值得研究。
答案 4 :(得分:0)
最好只在https上提供http内容
答案 5 :(得分:0)
有时候,在Facebook应用中,我们无法在安全页面中拥有非安全内容。我们也不能把这些内容制作成本地。例如,将在iFrame中加载的应用程序不是简单的内容,我们无法将其设置为本地内容。
我认为我们永远不应该在https中加载http内容,我们也不应该将https页面回退到http版本以防止错误对话。
确保用户安全的唯一方法是使用所有内容的https版本,http://developers.facebook.com/blog/post/499/
答案 6 :(得分:0)
接受的答案帮助我更新了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.php 有关CORS的更多信息,请参阅http://stackoverflow.com/questions/8719276/cors-with-php-headers?noredirect=1&lq=1
<?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;
}
答案 7 :(得分:-2)
简单地说:不要做。 HTTPS页面中的Http内容本质上是不安全的。点。这就是IE显示警告的原因。摆脱警告是一种愚蠢的h水手法。
相反,HTTPS页面应仅具有HTTPS内容。确保内容也可以通过HTTPS加载,如果页面是通过https加载的,则通过https引用。对于外部内容,这将意味着在本地加载和缓存元素,以便通过https - 确保它们可用。遗憾的是,没办法解决这个问题。
警告是有充分理由的。认真。花5分钟思考如何接管带有自定义内容的https显示页面 - 你会感到惊讶。
答案 8 :(得分:-3)
我意识到这是一个旧线程但只有一个选项就是从图片网址中删除http:部分,以便&#39; http://some/image.jpg&#39;成为&#39; // some / image.jpg&#39;。这也适用于CDN
答案 9 :(得分:-3)
最适合我的方式
<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" />