FacebookのIFrame方式で作成されたページは、一旦「アプリ」として作成してから、アプリのステータスページへ移動し、任意のFacebookに追加するステップを踏みます。

では、実際に追加する担当者が複数のFacebookページを管理していて、間違って全く別のFacebookページにIFrameを追加してしまった場合、どうなるでしょうか?

実は、そのまま表示できてしまいます。
追加はワンクリックでできてしまうので、クライアントや訪問者に指摘されるまで気付かない…という事態もありえます。また、ステータスページのURLは開発者であれば簡単に推測できるので、全く無関係のFacebookページにIFrameを追加されてしまうことも考えられます。
(後者=フリーライドについては未検証です)

追加自体は現時点では防げませんが、「指定したFacebookページ以外ではIFrameの中身を表示させない」ように、簡単なロックをかけることは可能です。

ソースコード

IFrameページをPHPが使用できるように作成し、文書のいちばん先頭に以下のスクリプトを追加します。
やや長いので、インクルードにした方が良いでしょう。

<?php
	if (isset($_POST['signed_request'])) {
		list($encoded_sig, $payload) = explode('.', $_POST['signed_request'], 2); 
		$data = json_decode(base64_decode(strtr($payload, '-_', '+/')), true);
	}

// 特定IDのFacebookページ以外で表示しようとするとエラーになります
	if (($data)&&($data['page']['id'] != 'XXXXXXXXXXXXX')){
		echo <<< EOL
<html>
<head>
	<title>エラーが発生しました</title>
	<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
</head>
<body>
	<p style="margin: 30px; text-align: center; color: red;">エラーが発生しました</p>
</body>
</html>
EOL;
		exit;
	}
?>

追加した後、途中の「XXXXXXXXXXXXX」となっている箇所は「許可したいFacebookページのID」に書き替えます。
これで、許可していないFacebookページに追加しても、赤文字でエラー文だけが表示されるようになります。

解説

Facebookページは表示の際、「signed_request」という情報をPOSTで送っています。この中には「現在IFrameで表示しているFacebookページのID」が含まれていて、デコードした後の配列から取得することができます。

signed_requestについては以下の記事を参照してください。

「signed_request」の情報が存在し、かつ取得した値が任意のFacebookIDと一致しているかを判定し、条件を満たさなければ強制終了します。

補足:1

このサンプルの場合、Frameの中身を設置したサーバーへ直接アクセスしたときは「signed_request」の情報がないので、普通に表示できます。
なので、単独表示でもエラーにしたい場合は、8行目の条件式を以下のように書き替えます。

尚、条件式を結んでいる「&&」は「かつ」、「||」は「または」を意味します。

if ((!$data)||($data['page']['id'] != 'XXXXXXXXXXXXX')){

補足:2

サンプルの認証方法は単純な方法なので、POSTを偽装された場合には対応していません。
さらに厳密に「signed_requestがFacebookから送信されたものか」を判定する場合は、以下の記事を参照してください。


普通の会社紹介ページなどが他のFacebookページで表示されても、特に実害はありません。
ですが、ゲームアプリだったり、お得な情報を配信するページだったりするなら、この手の対策はしておいた方が良さそうです。

いずれにしても、IFrameもしくはアプリを作成した場合は、所属するFacebookページがわかるよう、フッターにコピーライトを明記するなど、最低限の対策はしておきましょう。

この記事を書いた人

うぇびん

愛知県豊橋市に住んでいる、荒ぶるウェブおばさん。WordPressをはじめとした各種CMSを研究するのが好き。札幌のIT企業のビットスター株式会社に所属しています。