web-dev-qa-db-ja.com

HTTPSページのHTTPコンテンツを扱う

HTTPSを介して完全にアクセスされるサイトがありますが、時々外部コンテンツ HTTP(主にRSSフィードからの画像)を表示します。私たちのユーザーの大部分もIE6にこだわっています。

理想的には次の両方を行いたい

  • 安全でないコンテンツに関するIE警告メッセージを防止します(たとえば、以下のように画像をデフォルトのアイコンに置き換えることにより、あまり目立たないコンテンツを表示できます)
  • 他の方法では見ることができない画像の代わりに、ユーザーに役立つものを提示します。いくつかのJSがある場合、どのイメージがロードされていないかを把握し、代わりに私たちのイメージに置き換えることができます。

私は、最初の目的は単に可能ではないと思うが、2番目の目的で十分かもしれない。

最悪の場合のシナリオは、RSSフィードをインポートするときに解析し、画像をローカルに保存してユーザーがその方法でアクセスできるようにすることですが、それでもほとんど利益が得られないのは大変な苦痛のようです。

86
El Yobo

あなたの最悪のシナリオはあなたが思うほど悪くはありません。

すでにRSSフィードを解析しているので、画像のURLはすでにあります。 http://otherdomain.com/someimage.jpgのような画像URLがあるとします。このURLをhttps://mydomain.com/imageserver?url=http://otherdomain.com/someimage.jpg&hash=abcdeafadに書き換えます。このようにして、ブラウザは常にhttps経由でリクエストを行うため、問題を取り除くことができます。

次の部分-次のことを行うプロキシページまたはサーブレットを作成します-

  1. クエリ文字列からurlパラメーターを読み取り、ハッシュを確認します
  2. サーバーから画像をダウンロードし、プロキシしてブラウザに戻します
  3. オプションで、イメージをディスクにキャッシュします

このソリューションにはいくつかの利点があります。 htmlの作成時にイメージをダウンロードする必要はありません。画像をローカルに保存する必要はありません。また、あなたは無国籍です。 URLには、画像を提供するために必要なすべての情報が含まれています。

最後に、ハッシュパラメータはセキュリティ用です。構築した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);
    }    
}
146

HTTPS経由で画像をロードする簡単なソリューションを探している場合は、 https://images.weserv.nl/ にある無料のリバースプロキシサービスに興味があるかもしれません。それはまさに私が探していたものでした。

有料のソリューションをお探しの場合、以前はCloudinary.comを使用しましたが、これもうまく機能しますが、このタスクだけでは高すぎると思います。

12
nullable

これがあなたのやっていることに合うかどうかはわかりませんが、簡単な修正として、httpコンテンツをhttpsスクリプトに「ラップ」します。たとえば、httpsを介して提供されるページでは、rssフィードを置き換えるiframeを導入し、iframeのsrc attrに、フィードをキャプチャしてhtmlを出力するスクリプトのURLをサーバーに配置します。スクリプトはhttpを介してフィードを読み取り、httpsを介して出力します(つまり、「ラッピング」)

ちょっとした考え

3
Raine

2番目の要件について-onerrorイベントを利用できる場合があります。 <img onerror="some javascript;"...

更新:

Domでdocument.imagesを反復処理することもできます。使用できる可能性のあるcompleteブールプロパティがあります。これが適切かどうかはわかりませんが、調査する価値があるかもしれません。

2
UpTheCreek

Httpsにhttpコンテンツを置くだけが最善でしょう

0
Daniel

受け入れられた回答は、これを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 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;
}
0
CFP Support

Facebookアプリのように、安全なページに安全でないコンテンツを含めることはできません。また、それらのコンテンツをローカルにすることはできません。たとえば、iFrameに読み込まれるアプリは単純なコンテンツではなく、ローカルにすることはできません。

Httpsコンテンツをhttpsにロードすることは絶対にしないでください。また、エラーダイアログを防ぐためにhttpsバージョンをhttpバージョンにフォールバックしないでください。

ユーザーのセキュリティを確保する唯一の方法は、すべてのコンテンツのhttpsバージョンを使用することです http://developers.facebook.com/blog/post/499/

0