web-dev-qa-db-ja.com

HTTPSサイトでHTTPイメージを提供します。 「安全なドメイン」を追加できますか?

私はタイトルでこれが何度も尋ねられたかもしれないことを知っていますが、私は実際に同様の状況が尋ねられたのを見つけていませんでした(まあ、1)

SSL対応(https)のダッシュボードがありますが、ダッシュボードに関連する別のドメインおよび別のサーバーでホストされている、まだSSL対応ではない別のサイトの画像を表示する必要があります(http)。

私は、明らかな「他のサイトでSSLを有効にする」(私は取り組んでいますが、複雑です)とは別に、2つの異なる解決策を考えています。

私の最初の考えは、httpsサーバーのどこかにある特定のドメインをサーバーレベルで「許可」して、安全と見なされる特定のドメインからの非httpsトラフィックを「許可」できるかどうかです。それとも、これが起こることを許可しないブラウザのものですか?

それが不可能な場合、表示するためにhttpページからhttpsサイトにバックグラウンドで画像を「取得」する方法はありますか?プロキシとその方法について読んでいますが、これが正しいアプローチかどうかはわかりません。私のプログラミング言語はPHPです。イメージで「file_get_contents」を実行できるかどうか疑問に思っていますが、その後、イメージが一時的に保存される方法と場所を心配する必要があります。これはどういうわけかメモリに入れることができますか、または「ユーザーごと」に一時的に保存するにはどうすればよいですか?

明確にするために、これらは自分のサイトから自分のサイトへの画像です。私は奇妙なことや間違ったことをしようとはしていません(2番目のサイトのSSLが有効になっていないことは別として、もちろん正しい解決策です)。他の所有していないサイト/サーバーから画像を取得する方法を尋ねる人がたくさんいますが、それらは自分のサイトであるため、これらの両方を制御できます。

2
omega1

現実的には、オプションは次のとおりです。

(a)既に述べたように、SSLを使用して2番目のWebサイトをセットアップします。これはおそらく最良の長期ソリューションです。

(b)SSL対応Webサイトでプロキシスクリプトを使用して、他のサーバーから画像を提供します。この方法により、全体的な帯域幅の使用量が増加し、安全なWebサイトを実行するサーバーの動作がより困難になりますが、実際には、これは短期から中期のソリューションとして非常にうまく機能します。私はこの方法を数回使用しましたが、特定の目的には非常に効果的です。

これを実現するためにSSL対応WebサイトでホストされるPHPスクリプトの例は次のようになります。

<?php
const PROXY_DOMAIN = 'http://www.example-without-ssl.com/';

class AssetProxy {
  private $aHeaders;
  private $sData;

  public function __construct($sURL) {
    $this->aHeaders = array();
    $this->sData = '';

    /* HTTP 404 if resource does not exist */      
    if ($this->RemoteFileExists($sURL) == false) {
      header('HTTP/1.0 404 Not Found');
      exit;      
    }

    /* HTTP 304 if resource same as held in browser cache */
    $sData = @file_get_contents($sURL);
    $sETag = md5($sData);
    $this->aHeaders[] = sprintf('ETag: %s', $sETag);
    $sSuppliedETag = isset($_SERVER['HTTP_IF_NONE_MATCH']) ?
      $_SERVER['HTTP_IF_NONE_MATCH'] : '';
    if ($sSuppliedETag == $sETag) {
      header('HTTP/1.1 304 Not Modified');
      header('Content-Length: 0');
      exit;
    }

    /* Send asset with gzip compression */
    $this->DetectFileType($sURL);
    $this->SetBrowserCache(60 * 60 * 24 * 35); // 35 days
    if (!ob_start('ob_gzhandler')) ob_start();
    foreach ($this->aHeaders as $sHeader) header($sHeader);
    echo($sData);
  }

  private function RemoteFileExists($sURL) {
    $hCURL = curl_init($sURL);
    curl_setopt($hCURL, CURLOPT_NOBODY, true);
    $bResult = curl_exec($hCURL);
    if (!$bResult) return false;
    $iStatus = (int)curl_getinfo($hCURL, CURLINFO_HTTP_CODE);
    return ($iStatus == 200);
  }

  private function DetectFileType($sURL) {
    $sFileExtension = strtolower(substr($sURL, 1 + strripos($sURL, '.')));
    switch ($sFileExtension) {
      case 'js': $sMimeType = 'text/javascript'; break;
      case 'css': $sMimeType = 'text/css'; break;
      case 'swf': $sMimeType = 'application/x-shockwave-flash'; break;
      case 'png': $sMimeType = 'image/png'; break;
      case 'jpg': $sMimeType = 'image/jpeg'; break;
      case 'eot': $sMimeType = 'application/vnd.ms-fontobject'; break;
      default: $sMimeType = 'text/plain'; break;
    }
    $this->aHeaders[] = 'Content-Type: ' . $sMimeType . '; charset: UTF-8';
  }

  private function SetBrowserCache($iSeconds) {
    $dtNow = time();
    $dtExpires = strtotime(sprintf('+%s seconds', $iSeconds));
    $this->aHeaders[] = 'Expires: ' . date('r', $dtExpires);
    $this->aHeaders[] = 'Last-Modified: ' . date('r', $dtNow);
    $this->aHeaders[] = 'Cache-Control: public, must-revalidate, ' . 
      sprintf(max-age=%s', $iSeconds);
  }

}

$sAsset = isset($_GET['asset']) ? $_GET['asset'] : '';
$oProxy = new AssetProxy(PROXY_DOMAIN . $sAsset);
exit;

実際にプロキシスクリプトを提供するものではなく、このスクリプトをgzip.phpと呼ぶのが好きです。次に、HTMLで、出現するすべてのURLを変更します。

http://www.example-without-ssl.com/images/example.jpg

などの新しいURL

https://www.example-with-ssl.com/gzip.php?asset=images/example.jpg

このスクリプトファイルタイプにとらわれないため、JavaScript、スタイルシート、フォント、画像など、いくつかの異なるタイプの静的アセットを提供できます。さらにファイルタイプを追加するには、MIMEタイプをDetectFileType()関数に追加するだけです。そうしないと、デフォルトでtext/plain MIMEタイプが提供されます。

2
richhallstoke