处理 HTTPS 页面中的 HTTP 内容

发布于 2024-09-04 15:25:41 字数 404 浏览 4 评论 0 原文

我们有一个完全通过 HTTPS 访问的网站,但有时会显示 HTTP 的外部内容(主要来自 RSS 源的图像)。我们绝大多数用户还停留在IE6上。

,我希望执行以下两项操作

  • 防止 IE 关于不安全内容的警告消息(以便我可以显示侵入性较小的消息,例如,通过用默认图标替换图像,如下所示)
  • 理想情况下 向用户展示一些有用的内容来代替他们无法看到的图像;如果有一些 JS 我可以运行来找出哪些图像尚未加载并用我们的图像替换它们,那就太好了。

我怀疑第一个目标根本不可能实现,但第二个目标可能就足够了。

最糟糕的情况是,我在导入 RSS 提要时对其进行解析,抓取图像并将其存储在本地,以便用户可以通过这种方式访问​​它们,但这似乎带来了很大的痛苦,但收获却很少。

We have a site which is accessed entirely over HTTPS, but sometimes display external content which is HTTP (images from RSS feeds, mainly). The vast majority of our users are also stuck on IE6.

I would ideally like to do both of the following

  • Prevent the IE warning message about insecure content (so that I can show a less intrusive one, e.g. by replacing the images with a default icon as below)
  • Present something useful to users in place of the images that they can't otherwise see; if there was some JS I could run to figure out which images haven't been loaded and replace them with an image of ours instead that would be great.

I suspect that the first aim is simply not possible, but the second may be sufficient.

A worst case scenario is that I parse the RSS feeds when we import them, grab the images store them locally so that the users can access them that way, but it seems like a lot of pain for reasonably little gain.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

暖心男生 2024-09-11 15:25:41

最坏的情况并没有你想象的那么糟糕。

您已经在解析 RSS 提要,因此您已经有了图像 URL。假设您有一个类似 http://otherdomain.example/someimage.jpg 的图像 URL。您将此 URL 重写为 https://mydomain.example/imageserver?url=http://otherdomain.example/someimage.jpg&hash=abcdeafad。这样,浏览器始终通过 HTTPS 发出请求,从而解决了问题。

下一部分 - 创建执行以下操作的代理页面或 servlet -

  1. 从查询字符串中读取 URL 参数,并验证哈希值
  2. 从服务器下载图像,并将其代理回浏览器
  3. (可选)将图像缓存在磁盘

上解决方案有一些优点。您不必在创建 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);
    }
}

Your worst case scenario isn't as bad as you think.

You are already parsing the RSS feed, so you already have the image URLs. Say you have an image URL like http://otherdomain.example/someimage.jpg. You rewrite this URL as https://mydomain.example/imageserver?url=http://otherdomain.example/someimage.jpg&hash=abcdeafad. This way, the browser always makes request over HTTPS, so you get rid of the problems.

The next part - create a proxy page or servlet that does the following -

  1. Read the URL parameter from the query string, and verify the hash
  2. Download the image from the server, and proxy it back to the browser
  3. Optionally, cache the image on disk

This solution has some advantages. You don't have to download the image at the time of creating the HTML. You don't have to store the images locally. Also, you are stateless; the URL contains all the information necessary to serve the image.

Finally, the hash parameter is for security; you only want your servlet to serve images for URLs you have constructed. So, when you create the URL, compute md5(image_url + secret_key) and append it as the hash parameter. Before you serve the request, recompute the hash and compare it to what was passed to you. Since the secret_key is only known to you, nobody else can construct valid URLs.

If you are developing in Java, the Servlet is just a few lines of code. You should be able to port the code below on any other back-end technology.

/*
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);
    }
}
狂之美人 2024-09-11 15:25:41

如果您正在寻找通过 HTTPS 加载图像的快速解决方案,请使用 https://wsrv.nl/ 上的免费反向代理服务 您可能感兴趣。这正是我想要的。

示例:https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg

如果您正在寻找付费解决方案,我之前使用过 Cloudinary.com,它也运行良好,但在我看来,仅对于这项任务来说太昂贵了。

If you're looking for a quick solution to load images over HTTPS then the free reverse proxy service at https://wsrv.nl/ may interest you. It was exactly what I was looking for.

Example: https://wsrv.nl/?url=wsrv.nl/lichtenstein.jpg

If you're looking for a paid solution, I have previously used Cloudinary.com which also works well but is too expensive solely for this task, in my opinion.

秋心╮凉 2024-09-11 15:25:41

我不知道这是否适合您正在做的事情,但作为快速修复,我会将 http 内容“包装”到 https 脚本中。例如,在通过 https 提供服务的页面上,我将引入一个 iframe 来替换您的 rss feed,并在 iframe 的 src attr 中放置一个脚本的 URL,该脚本位于您的服务器上,用于捕获 feed 并输出 html。该脚本正在通过 http 读取 feed 并通过 https 输出(因此“包装”)

只是一个想法

I don't know if this would fit what you are doing, but as a quick fix I would "wrap" the http content into an https script. For instance, on your page that is served through https i would introduce an iframe that would replace your rss feed and in the src attr of the iframe put a url of a script on your server that captures the feed and outputs the html. the script is reading the feed through http and outputs it through https (thus "wrapping")

Just a thought

终止放荡 2024-09-11 15:25:41

关于您的第二个要求 - 您也许可以利用 onerror 事件,即。

更新:

您还可以尝试在 dom 中迭代 document.images 。您可以使用一个 complete 布尔属性。我不确定这是否合适,但可能值得研究。

Regarding your second requirement - you might be able to utilise the onerror event, ie. <img onerror="some javascript;"...

Update:

You could also try iterating through document.images in the dom. There is a complete boolean property which you might be able to use. I don't know for sure whether this will be suitable, but might be worth investigating.

岛徒 2024-09-11 15:25:41

接受的答案帮助我将其更新为 PHP 和 CORS,所以我想我会为其他人提供解决方案:

pure 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
请参阅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;
}

The accepted answer helped me update this both to PHP as well as CORS, so I thought I would include the solution for others:

pure 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
see http://stackoverflow.com/questions/8719276/cors-with-php-headers?noredirect=1&lq=1 for more on 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;
}
自我难过 2024-09-11 15:25:41

有时就像在 Facebook 应用程序中一样,我们不能在安全页面中包含非安全内容。我们也无法将这些内容本地化。例如,将在 iFrame 中加载的应用程序不是简单的内容,我们无法将其本地化。

我认为我们永远不应该在 https 中加载 http 内容,也不应该将 https 页面回退到 http 版本以防止出现错误对话框。

确保用户安全的唯一方法是使用所有内容的 https 版本,http://web.archive.org/web/20120502131549/http://developers.facebook.com/blog/post/499/

Sometimes like in facebook apps we can not have non-secure contents in secure page. also we can not make local those contents. for example an app which will load in iFrame is not a simple content and we can not make it local.

I think we should never load http contents in https, also we should not fallback https page to http version to prevent error dialog.

the only way which will ensure user's security is to use https version of all contents, http://web.archive.org/web/20120502131549/http://developers.facebook.com/blog/post/499/

浮华 2024-09-11 15:25:41

最好只有 https 上的 http 内容

It would be best to just have the http content on https

末蓝 2024-09-11 15:25:41

简单地说:不要这样做。 HTTPS 页面中的 Http 内容本质上是不安全的。观点。这就是 IE 显示警告的原因。摆脱警告是一种愚蠢的废话。

相反,HTTPS 页面应该包含 HTTPS 内容。确保内容也可以通过 HTTPS 加载,如果页面是通过 https 加载的,则通过 https 引用它。对于外部内容,这意味着在本地加载和缓存元素,以便可以通过 https 访问它们 - 当然。可悲的是,没有办法解决这个问题。

该警告的存在是有充分理由的。严重地。花 5 分钟思考如何使用自定义内容接管 https 显示的页面 - 您会感到惊讶。

Simply: DO NOT DO IT. Http Content within a HTTPS page is inherently insecure. Point. This is why IE shows a warning. Getting rid of the warning is a stupid hogwash approach.

Instead, a HTTPS page should only have HTTPS content. Make sure the content can be loaded via HTTPS, too, and reference it via https if the page is loaded via https. For external content this will mean loading and caching the elements locally so that they are available via https - sure. No way around that, sadly.

The warning is there for a good reason. Seriously. Spend 5 minutes thinking how you could take over a https shown page with custom content - you will be surprised.

美男兮 2024-09-11 15:25:41

我意识到这是一个旧线程,但一个选择是从图像 URL 中删除 http: 部分,以便 'http:// /some/image.jpg' 变为 '//some/image.jpg'。这也适用于 CDN

I realise that this is an old thread but one option is just to remove the http: part from the image URL so that 'http://some/image.jpg' becomes '//some/image.jpg'. This will also work with CDNs

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文