セキュリティ
Windows ランタイムと OAuth を使ってオンライン サービスにアクセスする
昔 Web 1.0 が使われていた頃の Web サイトは単に詰め込んだコンテンツを読み取るだけのものでした。開発部門に Web 2.0 が導入されると、Web サイトは API を備えたオンライン サービスとなり、開発者はこの API を使ってコンポーネント、データ、機能を組み合わせて対応できるようになりました。現在では、マッシュアップにより、データをサーバー ルームで管理するオーバーヘッドを必要としないで、機能豊富なコンテンツ ライブラリにアクセスできるようになっています。
Windows ランタイム (WinRT) により、次世代 Windows ストア アプリにマッシュアップの能力がもたらされます。XmlHttpRequest (XHR) を使用してデータを管理する場合でも、WebAuthenticationBroker クラスを使用してリモート サービスで認証する場合でも、JavaScript 用 Windows ライブラリ (WinJS) と Windows ランタイムを使えば、オンライン サービスとアプリを簡単に組み合わせることができます。
Contoso Photo Finish
今回は、Contoso Photo Finish というマッシュアップをビルドします。ランナーは、このアプリを使って、走行距離の記録や走行中の写真の投稿が可能です。多くのランナーは、自身が走った距離や場所などの情報をソーシャル ネットワークで共有しています。Contoso Photo Finish を使えば、ユーザーはコメントや写真を添えて Facebook で自身の走行を友人に伝えることができます。このアプリでは、次の 2 つの異なるサービスに接続します。
- 走行中の写真を取得するための Windows SkyDrive のサービス
- 友人に見せる写真を投稿するための Facebook のサービス
Contoso Photo Finish では、これらのサービスを組み合わせて、ユーザーに接続型のエクスペリエンスを提供します。ここでは、Visual Studio 2012 を利用でき、[JavaScript]、[Windows ストア]、[空のアプリケーション] テンプレートを操作してコーディングに着手できることを前提にしています。
マッシュアップの課題: 承認と認証
アプリ (Web アプリや Windows ストア アプリ) から Facebook にコンテンツを投稿する場合に克服すべき最初の課題は、認証です。Facebook では、だれが接続しているかを認識する必要があります。アプリにログインするユーザーは、ID (通常はユーザー名の形式) と資格情報 (パスワード、セキュリティ トークン、生体認証デバイスなど) を提示し、求められた ID にアクセス権があることを証明します。認証とは、提示された資格情報を使ってユーザーの ID を検証するプロセスのことです。
ユーザーを認証したら、マッシュアップは次の課題として、そのユーザーがシステム内で実行できることを決定する必要があります。承認とは、なんらかの属性やセキュリティ ロールのメンバーシップに基づいて、ある ID が実行しようとしている操作を許可または拒否するプロセスのことです。たとえば、Twitter の私の ID では、すべてのユーザーのすべてのツイートを削除することは許可されません。私はこの操作の実行が許可されるセキュリティ ロールのメンバーではないため、この操作を実行する権限がありません。この 2 つの認証と承認 (A&A) は、「ユーザーが何者で、どのような操作ができるか」という問いかけを表しています。
マッシュアップを作成する開発者は、ID、資格情報、およびセキュリティ ロールが格納されている場所 (資格情報ストア) にアクセスできないため、このような課題が深刻化します。では、ユーザーやユーザーが実行できる操作を開発者が確認できないとしたら、Facebook のようなアプリ向けのマッシュアップを作成するにはどうすればよいでしょう。ここで役に立つのが OAuth です。
OAuth: アプリではない、アクセス用のリソース
OAuth は、マッシュアップに関する A&A の課題に対処します。アプリ X が、オンライン サービス Y のコンテンツへのアクセスを希望しているとします。ユーザーの資格情報がオンライン サービス Y の資格情報ストアに格納されているため、ユーザーはアプリ X に対してではなくオンライン サービス Y に対して認証を行います。次に、ユーザーは、アプリ X がオンライン サービス Y の特定のリソースに期間限定でアクセスすることを許可します。オンライン サービス Y のリソースへのアクセス許可は、アクセス トークン (単に "トークン" と呼ばれることもあります) としてアプリ X に返されます。
従来の Web A&A モデルでは、ユーザーのアクセス権の判断にアプリとユーザー (またはサーバーとクライアント) の二者が関与します。OAuth では、3 番目の参加者としてリソース サーバーが関与します。リソース サーバーとは、クライアントがアクセスする必要のあるリソース (写真など) を格納するサーバーです。Contoso Photo Finish では、Facebook がリソース サーバーです。メッセージを投稿するため、Contoso Photo Finish からアクセスしたいリソースはユーザーのステータスです。
OAuth クライアントと認証のプロセス
OAuth には 2 種類のクライアントがあり、どちらのクライアントを使用するかはそのクライアントの信頼度のレベルによって決まります。Confidential クライアントは、資格情報のセキュリティを確保できるため、高い信頼度が求められる環境に適しています。Confidential クライアントの例には、セキュリティが確保される管理された環境でクライアント シークレットを管理できるサーバー側の Web アプリなどがあります。Confidential クライアントは、クライアントを認証する手段としてクライアント シークレットをリソース サーバーに提供し、承認コード プロセスを使用してセキュリティ トークンを取得します。
Public クライアントは、相手側の環境で実行されるため、資格情報のセキュリティを確保することはできません。Public クライアントの例には、ユーザー エージェント アプリ (JavaScript Web アプリ) やネイティブ アプリ (Windows ストア アプリなど) があります。Public クライアントは、"暗黙の権限付与" プロセスを使用してセキュリティ トークンを取得します。これは、クライアント シークレットを、開発者の制御が届かない相手側の環境に安全な方法で保存できないためです。
Windows ストア アプリを構成して、OAuth の暗黙の権限付与プロセスまたは承認コード プロセスを使用するようにできます (暗黙の権限付与プロセスおよび承認コード プロセスの詳細については、https://msdn.microsoft.com/ja-jp/library/live/hh243647.aspx を参照してください)。開発者の制御が届かない場所にあるアプリに対しては、常に暗黙の権限付与を使用するのがセキュリティのベスト プラクティスです。
図 1 では、暗黙の権限付与プロセスを示しています。ここでは、クライアントがリソース サーバーを使ってユーザーの ID を判断しようとするところから対話操作が始まります。
図 1 Windows ストア アプリの暗黙の権限付与の対話操作
図 1 で示した手順を説明します。
- Windows ストア アプリは、Facebook API へのアクセスを必要とする機能をいくつか実行する必要があります。
- ユーザーは、Facebook API にアクセスを試みる Windows ストア アプリについての情報を含む URI を使って、リソース サーバーに接続します。これは、通常アプリ ID やクライアント ID コードの形式で行います。ユーザーは、ユーザー名とパスワードを指定して Facebook にログインします。
- ログインが成功したとすると、Facebook から Windows ストア アプリにアクセス トークンが提供されます。
- Windows ストア アプリでは、Facebook から提供されたアクセス トークンを使用してユーザーのフィードの取得や写真の投稿などの操作を行い、Facebook API のデータをユーザーに提供できるようになります。
この対話操作は、新しい Windows.Security.Authentication.Web 名前空間によって驚くほど簡単に実現できます。
WebAuthenticationBroker
Windows ストア アプリにおいて、WebAuthenticationBroker クラス (https://msdn.microsoft.com/ja-jp/library/windows/apps/windows.security.authentication.web.webauthenticationbroker.aspx) は、リソース サーバーとの通信を行い、ログイン制御を提供して、成功したログイン操作に応答するコンポーネントです。これらすべてを行うのに、Windows ストア アプリがユーザーの資格情報を認識する必要はありません。今回のサンプル アプリでは、Contoso Photo Finish から Facebook に写真を投稿する必要があります。そのためには、ユーザーが Facebook に対するの認証を行い、アクセス トークンを取得することが必要です。
Contoso Photo Finish プロジェクトに input.html という新しいページ コントロールを追加します。Visual Studio は、既定で多数のマークアップを提供します。メイン コンテンツの "<p>コンテンツをここに挿入。</p>" を、次のボタンに置き換えます。
<input type="button" id="btnAddRun" value="Add Run" />
このボタンをユーザーがクリックすると、Photo Finish に走行の記録が追加されます。ここで、input.js を開いて次の関数を追加します。
function btnAddRun_Click(e) {
var facebookOauthUrl = "https://www.facebook.com/dialog/oauth";
var facebookClientId = "[YOUR CLIENT ID]";
var redirectUrl = "https://www.facebook.com/connect/login_success.html";
var requestUri = Windows.Foundation.Uri(facebookOauthUrl +
"?client_id=" + facebookClientId +
"&redirect_uri=" + encodeURIComponent(redirectUrl) +
"&response_type=" +
"token&scope=read_stream,publish_actions&display=popup");
var callbackUri = Windows.Foundation.Uri(redirectUrl);
// Web authentication broker will go here
}
このコードでは、認証要求で使用する変数を確立します。最初の変数は、Facebook OAuth サービスの URL です。クライアント ID は Facebook が使用するアプリ ID で、Contoso Photo Finish を Facebook API が対話操作するアプリとして特定します。通常、こうした ID はアプリがリソース サーバーに登録された時点でそのアプリに割り当てられます。リソース サーバーによっては、この ID をクライアント ID、アプリ ID、または単なる ID と呼びます。どの場合も、使用する ID はリソース サーバーの API ドキュメントで確認できます。
redirectUrl パラメーターは、アプリから特定のリソースへのアクセスをユーザーが認証および承認した後にアプリが移動する場所を決定します。今回は、すべての Facebook API アプリで使用できる Facebook 標準を redirectUrl に設定します。サービスによっては、Windows ストア アプリを登録するときに、アプリの URI がリソース サーバーで特定されることを必要とするサービスもあります。アプリの URI は、Web 認証ブローカーの getCurrentApplicationCallbackUri メソッドを使用して確認できます。このメソッドは、アプリの ("ms-app://" で始まる) ローカル コンテキスト URI を返します。ms-app:// が redirectUrl の有効なプロトコルとしてサポートされていないリソース サーバーでは、Facebook で提供されるような既定のリダイレクト アドレスを確認する必要があります。
次に、callbackUri を定義します。これは、認証がいつ完了し、いつ制御を Windows ストア アプリに戻すかを Web 認証ブローカーに知らせるアドレスです。ブローカーがこの URL に実際にアクセスすることはありません。ブローカーは、リソース サーバーがこのページを呼び出し、クエリ文字列やハッシュ パラメーターが付加された callbackUri を返すのを監視するだけです。このコードでは、API との対話操作に必要なトークンが、ハッシュ パラメーター "access_token" によって Contoso Photo Finish に提供されることになります。
WebAuthenticationBroker クラスは、authenticateAsync メソッドを使用して、リソース サーバーに接続し、認証プロセスを完了します。authenticateAsync が呼び出されると、アプリでポップアップが開き、リソース サーバーのログイン画面が表示されます (図 2 参照)。認証が完了するか、callbackUri が検出されると、ポップアップが閉じます。
図 2 authenticateAsync によって表示されるリソース サーバーのログイン用ポップアップ
このポップアップを使用する主なメリットは、リソース マネージャーのために Windows ストア アプリでユーザーの資格情報を処理したり認識したりする必要がないことです。アプリでは、リソース サーバーから返されるアクセス トークンを認識するだけです。このように処理を切り分けることで、リソース サーバーの資格情報をアプリから独立した状態に保ち、資格情報を保存するアプリのセキュリティに関するリスクを避けることができます。セキュリティ面のメリットがあるだけでなく、このインターフェイスを取得するコードは開発者が作成しなくても authenticateAsync メソッドに組み込まれているため、開発者がメソッドを呼び出せばそのインターフェイスも使用できます。
さて、コードに戻りましょう。"Web authentication broker will go here" (Web 認証ブローカーをここに挿入) というコメントを次のコードに置き換えます。
Windows.Security.Authentication.Web.WebAuthenticationBroker.
authenticateAsync(Windows.Security.Authentication.Web.
WebAuthenticationOptions.none, requestUri, callbackUri)
.done(
function (result) {
// Check the response status here
},
function (ex) {
Log(ex);
}
);
authenticateAsync メソッドは 3 つのパラメーターを受け取ります (3 つ目のパラメーターは省略可能です)。
- WebAuthenticationOptions: 認証ダイアログのレンダリング方法や、応答として返すデータについて、Web 認証ブローカーに指示を与えるのに使用します。上記の例では、アプリで "none" を使用することで、既定の設定を使用してブローカーにオプションを渡さない一般的な実装を示しています。
- requestUri: リソース サーバーのログイン用エントリ ポイントです。今回のコードでは、Contoso Photo Finish を Facebook の OAuth サービスに接続しています。requestUri は、HTTPS プロトコルを使用するセキュリティが確保された接続を経由する必要があります。
- callbackUri: 前述したように、(移動時に) Web 認証ブローカーに制御を返すページです。この引数は省略可能ですが、リソース サーバーで ms-app:// にリダイレクトできない (リダイレクトしない) 場合、このパラメーターはアプリがリソース サーバーの制御を免れる手段になります。たとえば上記のコードでは、ログインに成功した後 https://www.facebook.com/connect/login\_success.html に移動すると、認証ダイアログ ボックスを閉じて成功した promise を処理することで、Web 認証ブローカーがリソース サーバーからアプリの制御を受け取ります。直後のページを callbackUri にする必要はなく、リソース サーバーのサイトで確実に行われるウィザードなどの処理の後にしてもかまいません。この URI は、通常 redirectUrl と同じになりますが、必要に応じて認証プロセスを拡張する柔軟さも備えています。
Web 認証ブローカーからリソース サーバーに接続すると、promise の処理は成功です。認証プロセスの結果は、WebAuthenticationResult オブジェクトの ResponseStatus プロパティによって検出されます。上記のコードにおける結果の引数は、ResponseData (リソース サーバーのデータ)、ResponseErrorDetail (エラーが発生した場合のエラー)、および ResponseStatus (認証の状態) の 3 つのプロパティがある WebAuthenticationResult オブジェクトです。"Check the response status here" (ここで応答の状態を確認) というコメントを、図 3 に示すコードに置き換えます。
図 3 認証プロセスの結果の操作
switch (result.responseStatus) {
case Windows.Security.Authentication.Web.WebAuthenticationStatus.success:
var fragment = Windows.Foundation.Uri(result.responseData).fragment;
if (fragment.indexOf("#access_token=") != -1) {
var token = fragment.substring(
new String("#access_token=").length,
fragment.indexOf("&expires_in="));
// Add API calls here
}
break;
case Windows.Security.Authentication.Web.WebAuthenticationStatus.userCancel:
Log(window.toStaticHTML(result.responseData));
Display("User cancelled the authentication to Facebook.");
break;
case Windows.Security.Authentication.Web.WebAuthenticationStatus.errorHttp:
Log(window.toStaticHTML(result.responseData));
Display("An error occurred while communicating with Facebook.");
break;
}
図 3 のコードでは、リソース サーバーからの情報を記録する Log メソッドと、行われた処理をユーザーに伝える Display メソッドによってそれぞれの状態を確認します。エラー メッセージについては、使いやすくし、システムから生成されるエラー メッセージによって機密情報が誤って公開されないように、ユーザーにわかりやすいメッセージを表示するようにします。認証が成功すると、Facebook から返された URI フラグメントを解析し、API の呼び出しに使用するため token 変数に格納します (実装の詳細については、「XHR 経由で情報を取得および投稿する」を参照してください)。
btnAddRun_Click 関数が完成したら、この関数を WinJS.UI.Pages.define { ready } 関数で btnAddRun に結び付けます。
var btnAddRun = document.getElementById("btnAddRun");
if (null != btnAddRun)
btnAddRun.addEventListener("click", btnAddRun_Click, false);
この時点で、アプリには、リソース サーバーに対してユーザーが認証されていることを示すアクセス トークンがあります。アプリの最後のセクションではデータを送信する API コマンドを実行しますが、まずは、Facebook に送信するものがアプリに必要です。
写真を取得する
Windows 8 では、アプリどうしで対話できるさまざまなコントラクト (検索コントラクト、共有コントラクト、ファイル ピッカー コントラクトなど) が提供されます。これらのコントラクトにより、たった数行のコードであらゆるアプリをマッシュアップに変えることができます。Contoso Photo Finish では、ファイル ピッカー コントラクトの機能を利用して、ユーザーの走行中の画像を検索します。
Windows Phone で気に入っている点は多数ありますが、そのうちの 1 つが SkyDrive との統合です。クラウド内のストレージにすぐに写真をアップロードできるので、携帯電話を壊してしまっても (よくあることですが)、写真はオンライン上に残ります。データは Windows 8 向けの SkyDrive アプリによってファイル ピッカーに渡されるため、画像ライブラリからファイルを選択する程度の簡単さで SkyDrive アカウントからファイルを選択できます。Contoso Photo Finish マッシュアップの次の段階では、ファイル ピッカーを使って SkyDrive アプリのデータを使用します。そのために input.html に必要なものがあります。つまり、入力です。
btnAddRun ボタンを、図 4 に示すコードに置き換えます。このコードには、ユーザーが Contoso Photo Finish 向けにコンテンツを追加するための入力フィールドがあります。btnSelectPhoto ボタンはファイル ピッカーを使用して、システム上のどのファイルを使用するかを選択します。input.js に、btnSelectPhoto のクリック ハンドラーとなる新しい関数を追加します。
function btnSelectPhoto_Click(e) {
var imgSelectedPhoto = document.getElementById("imgSelectedPhoto");
var filePicker = new Windows.Storage.Pickers.FileOpenPicker();
filePicker.fileTypeFilter.replaceAll([".jpg", ".jpeg", ".png"]);
filePicker.suggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
filePicker.viewMode = Windows.Storage.Pickers.PickerViewMode.thumbnail;
// Pick file here
}
図 4 アプリ向けにコンテンツを追加する入力フィールド
<p>
<label>Distance</label>
<input type="number" min="0" max="15" id="txtDistance"
required /> miles
</p>
<p>
<label>Comment</label>
<input type="text" min="0" max="15" id="txtComment" />
</p>
<p>
<label>Photo</label>
<input id="btnSelectPhoto" value="Select Photo" type="button" />
<img src="" id="imgSelectedPhoto" alt="Selected Photo" />
</p>
<p>
<input type="button" id="btnAddRun" value="Add Run" />
</p>
この関数では、まず選択した写真をユーザーに表示するのに使用する imgSelectedPhoto 変数を設定します。次に、ファイル ピッカー オブジェクトを作成します。ファイル ピッカー オブジェクトを使用すると、Contoso Photo Finish で、システムまたはファイル ピッカー コントラクトに参加している他のアプリのファイルやフォルダー (今回はファイルのみ) を選択し、アプリ内で開いて操作できます。ファイルの種類に関するフィルターを使用して、ファイル ピッカーにアクセスできるファイル拡張子を制限します。今回のアプリでは、(設計上の理由から) Facebook に画像のみを読み込むことができます。したがって、ファイル ピッカーで特定の種類の画像ファイルだけを使用するように制限すると、目的の機能に適合しない無効な拡張子が含まれたファイルをユーザーが選択しないようにすることができます。また、画像に関するアプリのフォーカスの都合で、ファイル ピッカーの開始位置は画像ライブラリに設定しています。既定の場所はさまざまな場所 (音楽ライブラリ、ドキュメント ライブラリ、ホーム グループなど) に設定できますが、画像を処理する場合の常識的な開始点は画像ライブラリです。ファイル ピッカーに関する最後の設定は、viewMode の thumbnail への設定です。これにより、ファイルのプレビューが表示されるので、画像の選択に最適です。
オプションを設定したら、走行に関して使用するファイルを選択します。まず、"use strict" ステートメントの直後に次の 2 つの変数宣言を追加します。
var selectedPhotoStream = null;
var selectedPhotoFile = null;
これらの変数は、データを Facebook に読み込むときに、btnAddRun_Click 関数のためにファイルとストリームの値を保持します。"Pick file here" (ここでファイルを選択) というコメントを、図 5 に示すコードに置き換えます。
図 5 ファイルの選択
filePicker.pickSingleFileAsync().then(
function (storageFile) {
if (storageFile) {
selectedPhotoFile = storageFile;
selectedPhotoFile.openAsync(
Windows.Storage.FileAccessMode.read).then(
function (stream) {
selectedPhotoStream = stream;
document.getElementById("imgSelectedPhoto").src =
URL.createObjectURL(selectedPhotoFile);
},
function (ex) {
Log(ex);
Display("An error has occurred while reading the file.");
});
}
else {
Display("File was not selected");
}
});
図 5 はコードがたくさん記述されているように見えますが、3 つの処理に分類されます。
- ファイル ピッカー (pickSingleFileAsync) によりアプリで使用するファイルを選択する。
- 読み取るファイル ストリームを開く (openAsync)。
- 後で使用するために、ストリームとファイルを変数に格納する。
すべてのコードは、ファイルとストリームを操作する標準のコードですが、例外が 1 つあります。URL.createObjectURL は、オブジェクトを受け取り、画像オブジェクトを通じて表示するオブジェクトの URL を構築します。createObjectURL メソッドは、Stream、StorageItem、MediaCapture など多数のオブジェクトの種類に対応して、一般には、Windows ストア アプリでメディア コンテンツ (画像、オーディオ、またはビデオ) を表示するのに使用します。createObjectURL を使用する際の注意事項は、URL を使用し終わったときに、URL.revokeObjectURL メソッドを使用してその URL を破棄する必要があることです。これによりメモリ使用量を最適化し、一時的な URL が増えすぎて Windows ストア アプリがハングするのを防ぐことができます。createObjectURL の詳細については、MSDN ドキュメント (bit.ly/XdhzOm、英語) を参照してください。
最後に、btnSelectPhoto_Click イベントを btnSelectPhoto オブジェクトに関連付けます。WinJS.UI.Pages.define { ready } 関数に次のコードを追加します。
var btnSelectPhoto = document.getElementById("btnSelectPhoto");
if (null != btnSelectPhoto)
btnSelectPhoto.addEventListener(
"click", btnSelectPhoto_Click, false);
この時点で、投稿するコンテンツが Contoso Photo Finish に格納され、投稿のために Facebook への認証を行うメカニズムが揃いました。これで、アプリに必要なものは、API と対話操作を行うこととコンテンツをオンラインにすることだけになりました。
XHR 経由で情報を取得および投稿する
AJAX が目新しくて魅力的だった頃を思い出してください。XHR は、Internet Explorer 5.5 で導入され、Web 開発者が Web アプリの作成方法について考え直すきっかけを作りました。時は流れ、AJAX はさまざまなライブラリ (jQuery など) によって成長し、理解しやすく (さらに重要なことに) 実装しやすいソリューションになりました。この伝統は、シンプルな API を持つ WinJS.xhr に受け継がれ、データの取得やオンライン サービスへの投稿が行われています。
btnAddRun_Click 関数に戻り、"Add API calls here" (ここに API 呼び出しを追加) というコメントを、図 6 に示すコードに置き換えます。
図 6 selectedPhotoStream からの Blob オブジェクトの生成
var fileBlob = MSApp.createBlobFromRandomAccessStream(
selectedPhotoFile.contentType,
selectedPhotoStream);
var message = "I just ran " + document.getElementById(
"txtDistance").value + " miles with PhotoFinish! " +
document.getElementById("txtComment").value;
var data = new FormData();
data.append("source", fileBlob);
data.append("filename", selectedPhotoFile.name);
data.append("access_token", token);
data.append("message", window.toStaticHTML(message));
WinJS.xhr({
type: "POST",
url: "https://graph.facebook.com/me/photos",
data: data,
}).then(
function (photoid_response) {
ProcessResponse(photoid_response);
},
function (ex) {
Display("An error occurred while posting the photo.");
Log(ex);
});
既に、アプリで StorageFile と Stream を selectedPhotoFile 変数と selectedPhotoStream 変数に格納しました。MSApp.createBlobFromRandomAccessStream は selectedPhotoStream を受け取り、Blob オブジェクト (bit.ly/Stfu9z、英語) を生成します。この Blob オブジェクトは、POST パラメーターとして後でアプリから Facebook に渡されます。この機能は、WinRT オブジェクトを HTTP 経由で転送可能な形式に変換するのに便利です。
次に、コードで (HTML5 で新たに追加された) FormData オブジェクトを使用して、HTTP POST に送信するパラメーターを作成します。FormData は、キーと値を組み合わせたオブジェクトで、メソッドは append の 1 つのみです。append メソッドを使用すると、開発者はフォーム フィールドを動的に作成し、POST を使用して、フォームの送信イベントが呼び出された場合と同じようにそのフォーム フィールドを送信できます。また FormData では、パラメーターを、マルチパート/フォームデータのエンコーディングを伴うフォームに属している場合と同様に渡すことができます。これにより、開発者は (ファイルを含む) あらゆる種類の入力をターゲット サーバーに投稿できます。
FormData.append メソッド呼び出しで、toStaticHTML (bit.ly/ZRKBka、英語) を使用して、メッセージ コンテンツを送信しても安全であることを確認していることに注目してください。toStaticHTML を使用すると、message 変数を FormData オブジェクトに追加する前に、あらゆるイベント属性やスクリプト コンテンツが message 変数から削除されます。Facebook は (とりわけ) クロスサイト スクリプト攻撃を防ぐのに優れていますが、マッシュアップ開発者は、開発するアプリには簡潔なコンテンツを組み込みたいと考えます。インターネットは広大であるため、開発者全員がお互いに監視し合うことが必要です。
残りのコード ブロックは、WinJS.xhr の呼び出しです。今回はさらに、XHR の次の属性を使用しています。
- type: 使用する HTTP メソッドを設定します。既定では GET に設定しますが、このコードでは、アプリで Facebook API にコンテンツを送信するため POST を使用します。
- data: POST で渡すパラメーターを構成します。
メソッドが問題なく実行されて promise が返されると、Contoso Photo Finish では後で取得するための写真 ID を処理します。エラーが発生した場合は、標準エラー メッセージを表示して、例外をログ記録します。
WinJS.xhr には他の XHR ラッパーと似ている点が数多くあります。jQuery などの JavaScript ライブラリを使い慣れていれば、簡単に WinJS.xhr を選び出すことができます。直面する可能性のある問題は、XHR とは違って、WinJS.xhr メソッドにタイムアウトのオプションがない点です。タイムアウトは、WinJS.Promise.timeout メソッド (bit.ly/Qgtx7a、英語) を使って WinJS.xhr の呼び出しをラップすることで設定できます。WinJS.xhr の呼び出しの冒頭に次のコードを追加して、POST に対して 10 秒間のタイムアウトを設定します。
WinJS.Promise.timeout(1000, WinJS.xhr({ ... });
WinJS.xhr の promise が 10 秒以内に完了しなければ、promise はタイムアウトし、 promise のタイムアウト エラー関数で処理します。
アプリのマッシュアップへの第一歩
今回は、WinJS と Windows ランタイムを使用した認証、ファイルの取得、およびデータの送信について説明しました。このような基本スキルを積み重ねると、独自のイメージや開発者キー以外の制限がない Windows ストア アプリを設計できます。今回の資料を利用して、好みのオンライン サービスについて研究してください。WinJS.xhr を使用すると、オンラインで使用可能な無数の API を、独自の Windows ストア アプリで操作できます。Web 認証ブローカーを使用すると、アプリで OAuth や OpenID を使用して、ユーザーがオンラインの個人情報、コンテンツ、およびコミュニティにアクセスできるようにすることができます。WinJS および Windows ランタイムには、オンライン サービスを組み合わせたものよりも優れたアプリを容易に作成できるツールがすべて用意されています。
Tim Kulp は、ボルティモアの FrontierMEDEX で開発チームを率いています。彼は、ブログ (seccode.blogspot.com、英語) とツイッター (Twitter.com/seccode、英語) で、コード、セキュリティ、およびボルティモアの飲食店について話しています。
この記事のレビューに協力してくれた技術スタッフの Sunil Gottumukkala と Jeremy Viegas に心より感謝いたします。