SharePoint のページをフレーム (FRAME,IFRAME) 内に表示する方法について

こんにちは、SharePoint サポートの森 健吾 (kenmori) です。

今回の投稿では、SharePoint Online または SharePoint Server 2013 のページをフレーム内で表示すると "このコンテンツはフレーム内に表示できません。" とエラー発生する現象について原因と対処策をご説明します。
SharePoint Online や複数 On Premises など、様々な環境間でのハイブリッド運用シナリオが増えてきており、特に下記のようなシナリオで IFRAME を使用することが一般的となっています。

・ページ作成者が他ファームやテナントの Web パーツを表示する。
・アプリケーション開発者が、クロスドメイン制約をクリアするため JavaScript プログラミングでフレーム間通信 (window.postMessage) を実装する。

 このような状況において、突然本投稿のような現象に遭遇することは多いと思います。この投稿が問題解決の手掛かりにしていただけますと幸いです。

発生現象SharePoint Online または SharePoint Server 2013 では、フレームからページが呼び出された際に、親ウインドウ (呼び出し元) ページの URL が同じドメイン内でない場合は、フレーム内にページを表示することをブロックする動作となりました。
SharePoint 標準 Web パーツである ページ ビューア Web パーツを使用した場合でも、この動作の例外にはならず、別ファーム (または別テナント) にあるページを表示することはできません。

HTML

<html>
<iframe src="https://tenant.sharepoint.com/DocLib1/test.aspx" width="100%" height="100%"></iframe>
</html>

画面

上記画面のように "このコンテンツはフレーム内に表示できません。" というエラーが表示されます。

動作変更の経緯

このフレーム内のコンテンツを非表示に制御する仕組みは RFC 7034 においても規定され、クリック ジャッキングと呼ばれる攻撃に対処するために導入されました。

タイトル : HTTP Header Field X-Frame-Options
アドレス : https://tools.ietf.org/html/rfc7034

この規格によるブラウザーのセキュリティ強化を使用し、SharePoint Server は、HTTP 応答ヘッダーに X-FRAME-OPTIONS として SAMEORIGIN を指定することで、親フレームと URL のドメイン部分が異なる場合は、ブラウザーのフレーム内にコンテンツを表示させないよう制御します。
応答ヘッダーについては、ネットワーク パケットや Fiddler トレースを使用することで、下記の様に確認が可能です。

HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Type: text/html; charset=utf-8
Expires: Fri, 10 Oct 2014 15:02:23 GMT
Last-Modified: Sat, 25 Oct 2014 15:02:23 GMT
Server: Microsoft-IIS/7.5
X-SharePointHealthScore: 0
X-AspNet-Version: 4.0.30319
SPRequestGuid: 14a0c59c-a022-1000-988b-5dfbe61b59a8
request-id: 14a0c59c-a022-1000-988b-5dfbe61b59a8
X-FRAME-OPTIONS: SAMEORIGIN
SPRequestDuration: 432
SPIisLatency: 0

上記赤字で記載されている X-FRAME-OPTIONS 応答ヘッダーはブラウザーが、ページをフレーム内に表示するか制御するための設定を持つことができます。SharePoint が利用している主な設定値は下記ですが、応答ヘッダーが省略された場合にはすべて許可となります。

DENY 完全に禁止する
SAMEORIGIN アドレスのドメイン名が同じ場合のみ許可します

SharePoint Online の認証画面などでは DENY が使用されています。その他のページは SAMEORIGIN が使用されます。
SAMEORIGIN が指定された場合、https://tenant.sharepoint.com 内のページをフレーム内に表示する場合は、標準では https://tenant.sharepoint.com 内のページ コンテンツからのみに限定される動作となります。

X-FRAME-OPTIONS は近年追加されたセキュリティに対する比較的新しい機能となります。最新のブラウザーは、ほとんどが X-FRAME-OPTIONS 応答ヘッダーに対応しています。Internet Explorer については IE8 から対応しています。

タイトル : Internet Explorer 8 の新機能
アドレス : https://msdn.microsoft.com/ja-jp/library/cc288472(v=vs.85).aspx#%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e3%81%8a%e3%82%88%e3%81%b3%e3%83%97%e3%83%a9%e3%82%a4%e3%83%90%e3%82%b7%e3%83%bc

補足 : クリックジャッキング
ユーザーに気づかれないように、一般的には以下のようにページ上に透過処理させたページを重ねることで、ユーザーを騙して他のページを操作させる攻撃手法です。
ユーザーがインターネット上で色々なサービスにログインしたまま様々なページを閲覧していると、ユーザーのクリック操作が意図しない別ページ上のクリックと判断されてしまい損害を受ける状況が想定されます。このような攻撃からユーザーを守るために、サービスを提供する立場としては、できる限り X-FRAME-OPTIONS ヘッダーなどを指定し、ページのフレームによる用途を限定することが必要になります。

対処策

別ドメイン ページのフレームからアクセスを許可するページを作成する場合、AllowFraming コントロールを使用します。
AllowFraming コントロールはフレーム専用のページのみに使用してください。絶対にマスタページなどで使用しないでください。

タイトル : AllowFraming class
アドレス : https://msdn.microsoft.com/en-us/library/office/microsoft.sharepoint.webpartpages.allowframing(v=office.15).aspx

手順
1. SharePoint Designer でページを開きます。
2. ページヘッダーに Microsoft.SharePoint.WebPartPages 名前空間に対する参照がない場合は下記を追加します。
 <%@ Register tagprefix="WebPartPages" namespace="Microsoft.SharePoint.WebPartPages" assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

3. ページ内に AllowFraming コントロールを追記します。
  <WebPartPages:AllowFraming runat="server"/>

4. 下記のように追記したら、上書き保存します。

- 補足
・マスタ ページを参照した Web パーツ ページなどで実施する場合は、いずれかの PlaceHolder タグの子要素として AllowFraming コントロールを記載します。
・SPD による保存のタイミングで、WebPartId 属性などが付加されることがありますが、特に気にする必要はありません。

5. この対処を実施後、冒頭に紹介した IFRAME ページから呼び出します。

IFRAME 内に SharePoint Online 上に保存されたページが表示できました。

 

補足
AllowFraming は、SharePoint のページ ランタイム上で X-FRAME-OPTIONS: SAMEORIGIN 応答ヘッダーを返す動作を除外できます。
下記のいずれかを満たすことが、SharePoint のページ ランタイムによる X-FRAME-OPTIONS 応答ヘッダーを返す除外条件です

・ページが 2013 モードにビジュアル アップグレードされている
・HTTP 要求ハッシュ内に AllowFraming コントロールが生成する特殊なキーを含んでいない。

ただし、ビジュアル アップグレードについては前バージョンから使用していることが前提でありアップグレードしないことは推奨されません。

注意事項ページ作成者は、本対処策によりページ単位でクリック ジャッキング対策を無効にすることを考慮し、悪意のある第三者のページから、ユーザー データが改ざんされないように注意する必要があります。
そのため、下記の点については十分注意したページにすることをお勧めします。

・フレーム内にコンテンツを表示するページであれば、読み取り専用のビューとして作成する。
・クロスドメイン アクセスのためのデータ取得および更新ページであれば、window.postMessage メソッドを使用して処理要求を受信し、結果を返すのみに限定する。
 ユーザーがクリックできる形で、デバッグ用などの無用なコントロールを配置しない。

つまり、画面操作でデータ更新する動作が存在しないページについては、クリック ジャッキングによる攻撃の対象にはなりません。

なお、AllowFraming はあくまでクリックジャッキング対策であるフレーム内に別ドメインのページを表示するかどうかの制御のみに影響します。
ページ単位でこの設定を解除して、フレーム内にページを表示するようにできても、クロスサイト スクリプティング対策 (異なるドメインのフレームには JavaScript で DOM アクセスできない制御) には影響しませんのでご安心ください。

今回の投稿は以上となります。