Vaultモジュール
TD.Vaultモジュールは、Worklightの暗号化オフライン・キャッシュ(Encrypted Offline Cache:EOC)機能のラッパーです。EOCはローカル・ストレージ上にHTML5で作成され、cookieを使用しないで永続データを保管する方法となります。EOCには、ストレージをオープンおよびクローズするためのメソッド、そしてオープンされたストレージで値の読み取りおよび書き込みを行うためのメソッドが用意されています。EOCの背後にあるセキュリティーの詳細についてはこの記事では説明しませんが、要点を言えば、EOCはユーザー・パスワードを使用してデータを暗号化します。したがって、この特定のモジュールに関連するHTMLコードは、以下の要素が含まれるページ(図1の最初のパネル)となります。
- ロゴまたはアプリケーション名を表示するヘッダー・イメージ
- パスコードの入力フィールド (id=’passcode’)
- パスコードを送信するためのボタン (id=’send_passcode’)
<!-------------------------- PASSCODE PAGE --------------------------> <div data-role="page"> <img class="centerimg" src="images/logonobg.png"/> <div data-role="content"> <div class="center" id="invalid_passcode"></div> <ul data-role="listview" data-inset="true"> <li data-role="fieldcontain"> <label for="passcode">Enter Passcode:</label> <input type="text" name="passcode" id="passcode" value="" placeholder="Your passcode" /> </li> </ul> <a id="send_passcode" href="#" data-role="button" data-theme="a">Start</a> </div> <!-- /content --> </div> <!-- /page -->
JavaScriptコードでは、まず、グローバル変数を自動実行関数に渡します。この例で渡すグローバル変数は、jQuery$として再定義) とWL(WLとして再定義したWorklightの名前空間)です。次に、依存関係にローカル変数を割り当てることによって、依存関係を「キャッシュ」します。これにより、(WL名前空間をパラメーターとしてモジュールに渡すことなく)簡単にwl.EncryptedCache.openを呼び出して、eocという名前のローカル変数にwl.EncryptedCacheをキャッシュできるようになります。続いて、ユーザーが入力したパスフレーズをKEYというプライベート変数に格納し、パスコード・ボタン、パスコード・フィールド、そしてパスコードが無効な場合にエラー・メッセージを表示するdivに対応するDOM呼び出しを保存します(リスト10を参照)。
TD.namespace('TD.Vault'); TD.Vault = (function ($, wl) { //dependencies var eoc = wl.EncryptedCache, log = wl.Logger, list_obj = TD.List, CONST = TD.Constant, //private variables KEY = "", send_passcode_btn = $('#send_passcode'), passcode_fld = $('#passcode'), invalid_passcode_div = $('#invalid_passcode'),
Worklightの資料を調べて、onErrorHandler()コールバック関数から返されたステータス・コードに基づくエラー固有の処理を実装してください。
続いて、いくつかのプライベート関数を定義します。最初の_error()は、エラー・コールバックを受け取った場合にログに記録するだけの関数です。_setData()および_getData()メソッドは、それぞれ暗号化および復号するデータの取得方法と設定方法を指定します(リスト11を参照)。
//private functions _error = function () { log.debug("error"); }, _setData = function (new_list) { if (new_list) { list_obj.set(new_list); list_obj.refresh(); } }, _getData = function () { return list_obj.get(); },
イベント定義では、TD.Listと同様にsend_passcode_btnをクリック・イベントにアタッチし、ユーザーがアプリケーションの開始時に入力したパスコードの長さが1文字以上である場合、そのパスコードをプライベート変数KEYに割り当てます(リスト12を参照)。
send_passcode_btn.on('click', function () { var passcode = passcode_fld.val(); if (passcode.length > 0) { KEY = passcode; _decrypt(); $.mobile.changePage("#main", { transition: CONST.DEFAULT_TRANSITION }); } else { passcode_fld.val(''); invalid_passcode_div.text('Invalid Passcode.'); } });
次に、EOCの中身を復号するためにプライベート関数_decrypt()を呼び出します。この関数では、暗号化されたキャッシュをオープンした後に復号することになることを示す定数 (CONST.DECRYPT) を引数に指定して_open()を呼び出します。_open() 関数はeoc-openイベントをトリガーして該当するアクション(復号) を送信し、その結果として_read()が呼び出されます。_read()では、ユーザーが提供したキーを使用して、暗号化されたキャッシュの読み取りが試行されます。この時点で_setData()を呼び出し、parseJSON() によって構文解析されてJavaScript配列に戻されたデータを引数として渡します(この配列には、すべてのインデックスに対して1つの項目を表すキーと値のペアが含まれています)。キャッシュから何かが返された場合には、Listモジュールのset()を呼び出して、返されたリストを新しいリストとして設定します。そして最後に、TD.ListのPublic APIのrefresh()を呼び出して、HTMLのリスト要素を最新の表示に更新します。
_close = function () { var onCompleteHandler = function () { $.publish('eoc-closed'); }; //function(onCompleteHandler, onErrorHandler) eoc.close(onCompleteHandler, _error); }, _write = function () { var data = JSON.stringify(_getData()); //function(key, data, onCompleteHandler, onErrorHandler) eoc.write(CONST.TODO_ITEMS_KEY, data, _close, _error); }, _read = function () { var onCompleteHandler = function (data) { _setData($.parseJSON(data)); _close(); }; //function(key, onCompleteHandler, onErrorHandler) eoc.read(CONST.TODO_ITEMS_KEY, onCompleteHandler, _error); }, _encrypt = function () { _open(CONST.ENCRYPT); }, _decrypt = function () { _open(CONST.DECRYPT); }; $.subscribe("eoc-open", function (e, action) { if (action) { // == CONST.ENCRYPT _write(); } else { // == CONST.DECRYPT _read(); } });
暗号化もほとんど同じステップに従います。異なる点は、キャッシュをオープンした後のアクションが _read()ではなく_write()の呼び出しであることです。その後_getData()を実行して最新のリストを取得し、それをJSON.stringify()で文字列に変換した上で、そのストリングをキャッシュに格納します。暗号化および復号が完了するごとに、キャッシュをクローズしてください。
図4と図5に、完成したアプリケーションがiPhoneシミュレーター上で実行されている様子を示します。