JSON のセキュリティ対策は、以下の記事に記載した通りですが、これを PHP では組み込み関数で実現します。この記事では、JSON セキュリティ対策のサンプルプログラムを提示します。
PHP のクラスインスタンスを JSON に変換するには、組み込み関数のjson_encode を使用します。json_encode は、クラスインスタンスだけではなく、配列なども簡単に JSON に変換できます。
概要
この記事で作成する Web サービスでは、json_encode を使用して PHP クラスのインスタンスを JSON に変換します。PHP の場合は配列などを扱う方が適切かもしれませんが、他の言語のサンプルに合わせています。
クライアントからリクエストを受け取ると、Web サービスは該当するデータを検索して、一致したデータを JSON の形式でクライアントに返します。
呼び出し元のクライアントは、jQuery と prototype.js を使用した HTML を作成します。
Web サービスの作成
GET リクエストでパラメーターを受け付け、JSON で値を返すよう定義します。
・json.php
<?php //リクエストヘッダーチェック $headers = getallheaders(); if ($headers["X-Requested-With"] != "XMLHttpRequest") { header("HTTP/1.1 403 Forbidden"); exit; } //パラメータ取得 $name = $_GET["name"]; //名前検索 $person = searchList($name, createList()); //セキュリティヘッダー付与 header("Content-Type: application/json; charset=utf-8"); header('X-Content-Type-Options: nosniff'); //JSON 出力 echo json_encode($person); //Person クラス class Person { var $name; var $age; function __construct($_name, $_age) { $this->name = $_name; $this->age = $_age; } } //配列を作成 function createList() { $list = array(); $list[] = new Person("Yamada", 10); $list[] = new Person("Sato", 20); $list[] = new Person("Tanaka", 30); return $list; } //配列を検索 function searchList($name, $list) { foreach ($list as $person) { if ($person->name == $name) { return $person; } } return null; } ?>
クライアントの作成
Web サービスにリクエストを送信し、レスポンスのデータを表示するクライアントを作成します。レスポンスのデータを表示する際、HTML エスケープしていることに注意してください。
jQuery で作成
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <script src="js/jquery-2.0.3.min.js"></script> <script type="text/javascript"> $.ajax({ type: "GET", url: "/json.php", data: 'name=Yamada', success: function (data, textStatus, xhr) { //HTML escape and append $("#person").text(data.name + " " + data.age); } }); </script> </head> <body> <div id="person"></div> </body> </html>
実行結果は、以下のようになります。
Yamada 10
jQuery によって、以下の行がリクエストヘッダーに追加されていることに注意してください。
- X-Requested-With: XMLHttpRequest
GET http://192.168.11.9/json.php?name=Yamada HTTP/1.1 Host: 192.168.11.9 Connection: keep-alive Accept: */* X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36 Referer: http://192.168.11.9/json1.html Accept-Encoding: gzip,deflate,sdch Accept-Language: ja,en-US;q=0.8,en;q=0.6
以下の2行が、レスポンスヘッダー追加されていることに注意してください。
- Content-Type: application/json; charset=utf-8
- X-Content-Type-Options: nosniff
HTTP/1.1 200 OK Date: Mon, 05 Aug 2013 02:41:42 GMT Server: Apache X-Frame-Options: DENY X-Content-Type-Options: nosniff Content-Length: 26 Connection: close Content-Type: application/json; charset=utf-8
prototype.js で作成
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <script src="js/prototype.js"></script> <script type="text/javascript"> new Ajax.Request("/json.php", { method: "GET", parameters:{name:"Yamada"}, onSuccess: function (data) { //Text to JSON and security check var json = data.responseText.evalJSON(true); var str = json.name + " " + json.age; $("person").update(str.escapeHTML()); //HTML escape and update } }); </script> </head> <body> <div id="person"></div> </body> </html>
実行結果は、以下のようになります。
Yamada 10
prototype.js によって、以下の行がリクエストヘッダーに追加されていることに注意してください。
- X-Requested-With: XMLHttpRequest
GET http://192.168.11.9/json.php?name=Yamada HTTP/1.1 Host: 192.168.11.9 Connection: keep-alive Accept: text/javascript, text/html, application/xml, text/xml, */* X-Prototype-Version: 1.7.1 X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36 Referer: http://192.168.11.9/json2.html Accept-Encoding: gzip,deflate,sdch Accept-Language: ja,en-US;q=0.8,en;q=0.6
以下の2行が、レスポンスヘッダー追加されていることに注意してください。
- Content-Type: application/json; charset=utf-8
- X-Content-Type-Options: nosniff
GET http://192.168.11.9/json.php?name=Yamada HTTP/1.1 Host: 192.168.11.9 Connection: keep-alive Accept: text/javascript, text/html, application/xml, text/xml, */* X-Prototype-Version: 1.7.1 X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36 Referer: http://192.168.11.9/json2.html Accept-Encoding: gzip,deflate,sdch Accept-Language: ja,en-US;q=0.8,en;q=0.6
参考
Webアプリケーションセキュリティに関する記事は、以下のページにまとまっています。ぜひご確認ください。
コメント