HTTPSページのHTTPコンテンツを処理する


89

HTTPSを介して完全にアクセスされるサイトがありますが、HTTP(主にRSSフィードからの画像)である外部コンテンツを表示する場合があります。ユーザーの大多数もIE6を使用しています。

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

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

最初の目的は単に不可能であると思いますが、2番目の目的で十分かもしれません。

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

回答:


147

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

RSSフィードを既に解析しているので、すでに画像のURLを取得しています。のような画像のURLがあるとしますhttp://otherdomain.com/someimage.jpg。この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);
    }    
}

1
非常に健全で、これは私がこなすものだと思います。PHPを使用していますが、実装も簡単です。(パフォーマンスと帯域幅の使用のために)誰かが要求するたびにイメージをダウンロードしたくないので、私もキャッシュを実装します。セキュリティアプローチの提案も適切です(ただし、上記の標準のセキュリティモデルも適用します)。あなたの提案をありがとう。
El Yobo

32
このアプローチの唯一の重大な欠点は、すべての外部リソースを独自のシステム経由でルーティングすることです。これは法的責任であるだけでなく、かなり高額になる可能性もあります。
Tim Molendijk、2011

@TimMolendijkを2番目に追加し、コストとメンテナンスを追加するだけでなく、近くのサーバーにルーティングするか、アイドル状態のサーバーとバランスを取るはずのCDNを無効にします。
LeventePánczél2015年

2
NodeJSのソリューションは何ですか?
stkvtflw 2016

1
@TimMolendijkの別の+1が、解決策は何でしょうか?HTTPS経由で提供されるサイトは、HTTP経由で配信される画像でうまく機能しないようです
FullStackForger '11年

15

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

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


キャッチは何ですか?すばらしい作品
ジャック

5
@JackNicholson私は2年間、比較的大きな負荷のもとで使用しています。よく働く!2人の開発者への称賛。
ヌル可能

Httpで始まるリンク(ビデオまたはサイト)があり、httpsサイトのIframeに表示できません。これは非セキュアリンクであるため、機能していません。画像の場合、画像キャッシュを使用して問題を解決しました。誰もが任意のアイデアを持っている
INT14

@ int14 httpサイトのリバースプロキシを設定する必要があります。これは、AWS API Gatewayなどで行うことができます。
null可能

3

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

ちょっとした考え


これは私が今と同じ状況に私を残すだろうと私には思えます。私はすでにHTTPSページにコンテンツを表示しています-問題は、コンテンツに<img>タグがあり、http:// src値が含まれているため、表示されず、迷惑なメッセージが表示されることです。
El Yobo

そうです、画像への元のリンクを保持している場合、問題を回避する方法はありません。ラッパースクリプトは、RSSフィードのコンテンツをスキャンして画像を探し、それらを削除する必要があります。別のコメントで述べたように、ポップアップの原因となるコンテンツをロードして、代わりに何か有益な情報を表示したくない場合。それが「真ん中のスクリプト」の理由です
hndcrftd

メインのバックエンドスクリプトで、iframeなしでこれを実行することもできますが、この場合、rssフィードが返されて処理され、ページに出力されるのを待機しています。あなたのページがrssフィードと非同期で読み込まれるように、iFrameを実行します。iframeを回避するためにそこに行きたい場合は、ajaxオプションもあります。気になるところ-バックエンドプラットフォームは何ですか?
hndcrftd 2010年

2

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

更新:

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


興味深いことに、私はonerrorイベントがあったことさえ知りませんでした。(外部ソースから来ているため)HTMLを書き換える必要がありますが、HTML浄化機能で既にサニタイズされているため、フィルターとして追加することもできます。
El Yobo

JavaScriptが何かをする前にブラウザのセキュリティ警告が発生しませんか?
MrWhite 2016


0

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

エラーのダイアログを防ぐために、httpのコンテンツをhttpsにロードしないでください。また、httpsページをhttpバージョンにフォールバックしないでください。

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


3
これはFacebookで可能かもしれませんが、すべてのコンテンツに対してではなく、この質問はFacebookに関するものではありませんでした。
El Yobo、2012年

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;
}

-2

単に:それをしないでください。HTTPSページ内のHttpコンテンツは本質的に安全ではありません。ポイント。IEが警告を表示するのはこのためです。警告を取り除くことは愚かな大掃除のアプローチです。

代わりに、HTTPSページがすべきのみはHTTPSコンテンツをがあります。コンテンツがHTTPS経由でもロードできることを確認し、ページがhttps経由でロードされている場合はhttps経由でコンテンツを参照します。外部コンテンツの場合、これは、要素をローカルでロードおよびキャッシュして、https経由で利用できるようにすることを意味します。残念ながらそれを回避する方法はありません。

警告は正当な理由でそこにあります。真剣に。カスタムコンテンツを含むhttps表示ページをどのように引き継ぐことができるかを5分間考えます。


3
そこには簡単ですが、それには十分な理由があることを認識しています。この点で、IEの動作はFFよりも優れていると思います。私が目指しているのは、コンテンツをロードすることではありません。煩わしいポップアップスタイルの警告を回避し、コンテンツの代わりに有益な情報を表示したいだけです。
El Yobo

2
その可能性はありません-途中でHTMLを書き換えない限り。JavaScriptのポストロードの試行はすでにダイアログを表示しています。
TomTom

彼は単に画像について尋ねていて、安全でないテキストやスクリプトを要求していないので、URLを書き換えて警告を渡すことができます。
ジャヤパルチャンドラン、2011

1
答えは変わりません。画像も安全でない可能性があります。これは一般的なことです。セキュリティで保護されたソースからのものであるか、中間の攻撃者によって置き換えられる可能性があります。
TomTom

8
この「回答」がOPの目標を達成する方法に回答しなかったため、反対票が投じられました。
MikeSchinkel 2014年

-3

これは古いスレッドですが、1つのオプションは、http:部分を画像URLから削除して、「http://some/image.jpg」が「//some/image.jpg」になるようにすることです。これはCDNでも機能します


7
これは時々機能し、時々機能しません。アップストリームコンテンツがHTTPS経由で利用できるかどうかによって異なります。そうでない場合は、壊れます。
El Yobo 2016年

-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" /> 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.