この記事は機械翻訳されたものです。

Silverlight のセキュリティ

Silverlight アプリケーションを保護する

Josh Twist

Microsoft Services のコンサルタントとして、私はお客様やパートナー様とアプリケーションのセキュリティについて定期的に話し合っています。 この記事では、そのような話し合いの中で出てきたテーマをいくつか紹介します。 具体的には、Silverlight アプリケーションを保護する際にプログラマが直面する新しい課題を主に取り上げ、開発チームはどのリソースに重点を置くべきかを考察します。

この記事では、さまざまな技術的な考え方に触れますが、それらについての詳細は別の参考資料 (MSDN Magazine を含む) で説明されています。 したがって、それらの考え方の技術的な詳しい説明には踏み込みません。 この記事の目標は、"点を線で結び"、それらの考え方を利用してアプリケーションを保護する方法を説明することです。

アプリケーションのセキュリティを計画するときは、authentication (認証)、authorization (承認)、および audit (監査) の 3 つの A を考えると便利です。

認証: ユーザー自身が主張するユーザーであることを確認する行為。 通常、これにはユーザー名とパスワードが使用されます。

承認: 認証後に、特定の操作の実行や特定のリソースへのアクセスに必要となる適切なアクセス許可が、実際にユーザーに付与されていることを確認するプロセス。

監査: ユーザーには拒否できない、システムに対して実行された操作や要求などのアクティビティの記録を取る行為。

ここでは、Silverlight アプリケーションにおける最初の 2 つの A (認証と承認) について説明します。 Silverlight アプリケーションは、Rich Internet Application (RIA) であるため、この記事で説明している考え方の大半は、Asynchronous JavaScript や XML (AJAX) など、他の RIA 技術にも当てはまります。 また、Silverlight アプリケーション ファイルへの望ましくないアクセスを防止する方法についても説明します。

トポロジ

Silverlight は、Windows Presentation Foundation (WPF) から生まれ、グラフィック関連の考え方の多くを取り入れたクロス ブラウザー プラグインで、HTML や JavaScript だけでは実現できないユーザー エクスペリエンスを開発できます。

ASP.NET と異なり、Silverlight はクライアント側のテクノロジであるため、ユーザーのコンピューター上で実行されます。 したがって、Silverlight 開発は、一概には言えませんが、ASP.NET よりも Windows Forms や WPF と共通する点が多いと言えます。 ユーザーのコンピューター上で実行できることは、いろいろな意味で Silverlight の最大のメリットの 1 つです。これにより、Web アプリケーションがステートレスであることに起因する問題の多くが解消されるためです。 ただし、すべての UI コードがクライアント コンピューター上で実行されるため、信頼性は失われます。

サービス

Windows フォームと異なり、Silverlight はブラウザーのサンドボックス内で稼働し、機能が削減されているため、セキュリティのレベルは向上しています (ただし、Silverlight 4 では、ユーザーが特定のアプリケーションを信頼できるアプリケーションとして指定し、そのアプリケーションの特権レベルを上げて COM 相互運用を許可できます)。 このため、Silverlight からは直接データベースに接続できません。したがって、データやビジネス ロジックへのアクセスを提供するサービス層を作成する必要があります。

通常、このようなサービスは、たとえば ASP.NET Web フォームの場合と同様に、Web サーバーでホストします。 Silverlight コードは、サーバーとサーバー外部間の信頼境界の信頼されない側で実行されることを踏まえて (図 1 参照)、常にサービスの保護を中心にセキュリティ対策を講じるようにします。

Figure 1 Silverlight Runs on the Wrong Side of the Trust Boundary
図 1 信頼境界の信頼されない側で稼働する Silverlight

Silverlight コード自体には、厳格なセキュリティ チェックを実装できる箇所はほとんどありません。 結局のところ、Silverlight アプリケーションをまったく通過せずにサービスを直接起動し、実装したセキュリティ対策を回避することは攻撃者にとって簡単です。 または、悪意のある人物が、Silverlight Spy や Windows 用のデバッグ ツールを使用して、実行時のアプリケーションの動作を変更する可能性もあります。

この認識は重要です。つまり、サービスからは、どのアプリケーションから起動されているかや、起動元のアプリケーションがなんらかの形で変更されていることはわかりません。 したがって、サービスでは次のことを確認する必要があります。

  • 呼び出し元が正しく認証されている
  • 呼び出し元は要求された操作を実行することが承認されている

上記の理由から、この記事のほとんどの部分では、Silverlight から利用できる方法でサービスを保護する方法について説明します。 具体的には、Microsoft IIS の ASP.NET を通じてホストされる 2 種類のサービスについて考察します。 1 つは Windows Communication Foundation (WCF) を使用して作成されるサービスで、サービスを構築するための統一されたプログラミング モデルを提供します。 2 つ目は、WCF を基盤とした WCF Data Services (以前は ADO.NET Data Services) で、Representational State Transfer (REST) と呼ばれる方法で、標準の HTTP 動詞を使用してすばやくデータを公開します。

当然、セキュリティが懸念される場合は、クライアントとサーバー間の通信を暗号化するのが定石です。 HTTPS/SSL 暗号化の使用をお勧めします。また、この記事では HTTPS/SSL 暗号化を使用することを前提としています。

現在、Web 開発者が Microsoft プラットフォームで使用する最も一般的な認証方法は、Windows 認証とフォーム認証の 2 つです。

Windows 認証

Windows 認証では、ローカル セキュリティ機関または Active Directory を使用してユーザーの資格情報を検証します。 これは、システム管理者が使い慣れたツールを使用してユーザーを一元管理できるため、多くのシナリオで非常に有効です。 Windows 認証では、基本、ダイジェスト、統合認証 (NTLM/Kerberos)、証明書のどの方式でも、IIS によってサポートされる方式であれば使用できます。

統合認証方式では、2 回目以降にユーザーがユーザー名とパスワードを入力する必要がないため、Windows 認証で使用される最も一般的な方式です。 ユーザーが Windows にログオンすると、ブラウザーがそのユーザーの身元を保証するトークンまたはハンドシェイクの形で資格情報を転送します。 統合認証を使用する場合は、クライアントとサーバーの両方でユーザーのドメインが認識される必要があるため、いくつか欠点があります。 したがって、統合認証はイントラネット シナリオでの使用が最適です。 また、Microsoft Internet Explorer では自動的に有効になりますが、Mozilla Firefox などの他のブラウザーでは追加の構成が必要です。

基本認証とダイジェスト認証では、通常、Web サイトとのセッションを開始するときに、ユーザー名とパスワードの再入力が必要です。 ただし、どちらも HTTP 仕様に含まれているため、組織の外部からアクセスする場合であっても、ほとんどのブラウザーで使用できます。

Silverlight では通信にブラウザーを利用するため、上記の IIS 認証手法のいずれでも、Windows 認証を簡単に実装できます。 実装方法の詳細については、「方法: Windows フォームから basicHttpBinding および WCF の TransportCredentialOnly を使用した Windows 認証を使用する」(msdn.microsoft.com/library/cc949012、英語) というステップ バイ ステップ ガイドを参照してください。 このガイドの例では、Windows フォームのテスト用クライアントが使用されていますが、Silverlight でも同じ方法を利用できます。

フォーム認証

フォーム認証は、カスタム認証を簡単にサポートできるようにする ASP.NET のメカニズムです。 したがって、HTTP 用のメカニズムであり、Silverlight でも簡単に使用できます。

ユーザーがユーザー名とパスワードを入力すると、検証のためにこの情報がサーバーに送信されます。 サーバーは、信頼されたデータ ソース (多くの場合、ユーザーのデータベース) を基にこの資格情報を確認し、情報が正しい場合は、FormsAuthentication Cookie を返します。 クライアントは、これ以降の要求ではこの Cookie を提示します。 Cookie は署名および暗号化されているため、暗号化を解除できるのはこのサーバーのみで、悪意のあるユーザーは Cookie の暗号化を解除することも、改ざんすることもできません。

フォーム認証を実行する実際の方法は、ログイン画面の実装方法に応じて異なります。 たとえば、ユーザーの資格情報の検証後に Silverlight アプリケーションにリダイレクトされる ASP.NET Web フォームを使用している場合は、おそらくこれ以上の認証処理は必要ありません。 Cookie は既にブラウザーに送信されており、Silverlight アプリケーションはドメインへの要求を実行する場合、いつでもその Cookie を継続して使用できます。

ただし、Silverlight アプリケーション内にログイン画面を実装する場合は、認証方法を公開し、適切な Cookie を送信するサービスを作成する必要があります。 さいわい、ASP.NET には必要なもの (認証サービス) が既に用意されています。 アプリケーションでこの認証サービスを有効にするだけで、対応できます。 詳細については、「方法: ASP.NET 認証サービスを使用して、Silverlight アプリケーションにログインする」(msdn.microsoft.com/library/dd560704(VS.96)、英語) を参照してください。

ASP.NET 認証の優れた特性としては、拡張性も挙げられます。 メンバーシップ プロバイダーが、ユーザー名とパスワードの検証に使用するメカニズムを記述します。 さいわい、ASP.NET には、SQL Server データベースを使用できるものや、Active Directory を使用できるものなど、さまざまなメンバーシップ プロバイダーが用意されています。 ただし、要件に合うプロバイダーがなくても、カスタム実装を簡単に作成できます。

ASP.NET での承認

ユーザーが認証されたら、認証されたユーザーしかサービスを呼び出せないようにすることが重要です。 通常の WCF サービスも、WCF Data Services も、ASP.NET アプリケーションでは .svc ファイルで表されます。 ここでの例では、IIS の ASP.NET を使ってサービスをホストし、フォルダーを使用してそのサービスへのアクセスを保護する方法を紹介します。

このようなファイルに対する要求の場合、既定では、ASP.NET パイプラインのほとんどがスキップされ、認証モジュールがバイパスされるため、この方法での .svc ファイルの保護はやや複雑です。 そこで、ASP.NET 機能の多くを利用できるようにするため、ASP.NET 互換モードを有効にする必要があります。 WCF Data Services の場合は、どのような場合でも ASP.NET 互換モードを有効にする必要があります。 ASP.NET 互換モードは、構成ファイル内で簡単なスイッチを設定するだけで有効にできます。

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
</system.serviceModel>
<system.web>
    <authorization>
        <deny users="?"/>
    </authorization>
</system.web>

ASP.NET 互換モードが有効になると、web.config の authorization セクションを使用して、未認証ユーザーからのアクセスを防止できます (これについても、上記のコード スニペットを参照)。

フォーム認証を使用する場合、未認証ユーザーに対する公開も含め、サイトのどの部分をアクセス可能にするかを慎重に検討する必要があります。 たとえば、すべての部分を認証済みユーザーにしか公開しないのであれば、未認証ユーザーのログイン方法をどのようにするかを考えます。

多くの場合、最も簡単なのは、基本的な認証要件をサポートするフォルダー構造を作成することです。 ここでの例では、MyWcfService.svc と MyWcfDataService.svc というフォルダーを含む "Secured" フォルダーを作成し、web.config ファイルを配置しています。 図 2 は、このフォルダー構造を示しています。また、前出のコード スニペットは、この例の web.config ファイルの内容です。

Figure 2 Secured Folder Containing the Web.config File
図 2 Web.config ファイルが格納されている保護されたフォルダー

アプリケーションのルートでは、匿名アクセスを許可する必要があります。そうしないと、ユーザーがログイン ページにアクセスできません。

Windows 認証を使用するサイトの場合、この点は多少簡単です。このようなサイトでは、ユーザーがアプリケーション内のリソースにアクセスする前に認証が実施されるため、特定のログイン ページは必要ありません。 この方法を使用すると、サービスへのアクセスを細かく制限でき、特定のユーザーまたは役割のグループにのみリソースのアクセスを許可できます。 詳細については、「ASP.NET の承認」(msdn.microsoft.com/library/wce3kxhd) を参照してください。

ここでの例では、ある程度の認証を実装していますが、フォルダー レベルの認証だけでは不十分で、ほとんどのシナリオでは信頼できません。

WCF サービスでの承認

Microsoft .NET Framework メソッドの呼び出し元が特定の役割のユーザーであることを必須とする簡単な方法としては、PrincipalPermission 属性を使用します。 次のコード サンプルでは、WCF の ServiceOperation に PrincipalPermission 属性を適用する方法を示しています。ここでは、呼び出し元のユーザーが "OrderApprovers" 役割のユーザーであることを要求しています。

[PrincipalPermission(SecurityAction.Demand, Role = "OrderApprovers")]
public void ApproveOrder(int orderId)
{
  OrderManag-er.ApproveOrder(orderId);
}

この方法は、Windows 認証を使用して、ユーザーの整理に Active Directory グループを作成する既存の機能を利用するアプリケーションの場合は、簡単に実装できます。 フォーム認証を使用するアプリケーションの場合は、ASP.NET のプロバイダー ベースの便利な機能である RoleProviders を利用することができます。 この機能もさまざまな種類が用意されていますが、適したものがなければ独自に実装できます。

もちろん、メソッド単位の承認もセキュリティ ニーズのすべてを満たせることはほとんどありませんが、どのような場合でもサービス内に手続き型のコードを作成できます (図 3 参照)。

図 3 手続き型のコードを使用した特定の認証の実装

Public void CancelOrder(int orderId)
{
  // retrieve order using Entity Framework ObjectContext
  OrdersEntities entities = new OrdersEntities();
  Order orderForProcessing = entities.Orders.Where(o => o.Id == 
    orderId).First();

  if (orderForProcessing.CreatedBy != 
    Thread.CurrentPrincipal.Identity.Name)
  {
    throw new SecurityException(
      "Orders can only be canceled by the user who created them");
  }

  OrderManager.CancelOrder(orderForProcessing);
}

WCF は非常に拡張性が高いプラットフォームであり、WCF の他のすべての機能と同様に、承認をサービスに実装する方法は多数あります。 Dominick Baier と Christian Weyer が、2008 年 10 月号の MSDN Magazine で、さまざまな方法について詳しく説明しています。 「WCF ベースのサービスでの承認」(msdn.microsoft.com/magazine/cc948343) という記事では、アプリケーション内の承認を構造的に整理できる、クレーム ベースのセキュリティも取り上げられています。

WCF Data Services での承認

WCF Data Services は、名前が示すとおり、データ ソース (おそらく、最も一般的には LINQ-to-SQL データ ソースや LINQ-to-Entity Framework データ ソース) への REST ベースのアクセスを提供する WCF を基盤とするサービスです。 簡単に説明すると、WCF Data Services では、データ ソースによって公開されるエンティティ セットにマップする URL (通常は、データベース内のテーブルにマップするエンティティ セット) を使用して、データへのアクセスを提供します。 このようなエンティティ セットに対するアクセス許可は、サービスの分離コード ファイル内に構成できます。 図 4 は、MyWcfDataService.svc.cs ファイルの内容を示しています。

図 4 エンティティ セットのアクセス規則が構成されている WCF Data Services 分離コード ファイル

Public class MyWcfDataService : DataService<SalesEntities>
{
  // This method is called only once to initialize service-wide policies.
  Public static void InitializeService(IDataServiceConfiguration config)
  {
    config.SetEntitySetAccessRule("Orders", EntitySetRights.AllRead);
    config.SetEntitySetAccessRule("Products", EntitySetRights.AllRead | 
      EntitySetRights.WriteAppend | EntitySetRights.WriteDelete);
  }}

ここでは、Orders エンティティ セットに読み取りアクセス許可を付与し、Products エンティティ セットでは完全な読み取り、新規レコードの挿入、および既存のレコードの削除を許可するように構成しています。

ただし、WCF Data Services によって、この構成を基盤とするデータへのアクセスが自動的に提供され、コードに直接アクセスできないため、明らかに特定の承認ロジックを実装できる箇所はありません。 WCF Data Services では、クライアントとデータ ソース間にロジックを実装できるインターセプターをサポートしています。 たとえば、特定のエンティティセットに対する結果をフィルター処理するクエリ インターセプターを指定できます。 図 5 の例では、MyWcfDataService クラスに追加された 2 つのクエリ インターセプターを示しています。

図 5 WCF Data Services のクエリ インターセプター

[QueryInterceptor("Products")]
Public Expression<Func<Product, bool>> OnQueryProducts()
{
  String userName =ServiceSecurityContext.Current.PrimaryIdentity.Name;
  return product => product.CreatedBy == userName;
}

[QueryInterceptor("Orders")]
Public Expression<Func<Comments, bool>> OnQueryOrders()
{
  bool userInPrivateOrdersRole = 
    Thread.CurrentPrincipal.IsInRole("PrivateOrders");
  return order => !order.Private|| userInPowerUserRole;
}

最初のインターセプターは Products エンティティ セットに適用され、自分で作成した製品しかユーザーが取得できないようにしています。 2 つ目のインターセプターでは、PrivateOrders の役割のユーザーしか、Private が設定されている注文を読み取れないようにしています。

同様に、次に示すように、エンティティが挿入、変更、または削除される前に実行される変更インターセプターを指定することもできます。

[ChangeInterceptor("Products")]
public void OnChangeProducts(Product product, UpdateOperations operations
{
  if (product.CreatedBy != Thread.CurrentPrincipal.Identity.Name)
  {
    throw new DataServiceException(
      "Only products created by a user can be deleted by that user");
  }
}

一見すると、このコード サンプルの OnChangeProducts 変更インターセプターは、外部ソースから渡されるデータ ("product" パラメーター) に実装を依存しているため、セキュリティの脆弱性があるように思えます。 しかし、WCF Data Services のエンティティを削除しているときは、クライアントからサーバーにエンティティ キーしか渡されません。 つまり、エンティティ自体 (この例では Product) は、データベースからのフェッチを再度実行する必要があるため信頼できます。

ただし、既存のエンティティに対する更新の場合 (たとえば、操作パラメーターが UpdateOperations.Change の場合)、製品パラメーターはクライアントによって送信されるシリアル化解除されたエンティティになります。 クライアント アプリケーションは、この特定の製品の CreatedBy プロパティを悪意のあるユーザー自身の ID に指定するように変更され、不正な特権に昇格されている可能性があります。 その結果、権限のないユーザーによる製品の変更が許可される可能性があります。 これを防ぐため、エンティティ キーのみを基に、信頼されるデータ ソースから元のエンティティを再度フェッチすることをお勧めします (図 6 参照)。

図 6 未承認の挿入、更新、および削除操作を防ぐ変更インターセプター

[ChangeInterceptor("Products")]
Public void OnChangeProducts(Product product, UpdateOperations operations)
{
  if (operations == UpdateOperations.Add)
  {
    product.CreatedBy = Thread.CurrentPrincipal.Identity.Name;
  }
  else if (operations == UpdateOperations.Change)
  {
    Product sourceProduct = this.CurrentDataSource.Products.Where(p =>
      p.Id == product.Id).First();
    if (sourceProduct.CreatedBy != Thread.CurrentPrincipal.Identity.Name)
    {
      throw new DataServiceException(
        "Only records created by a user can be modified by that user");
    }
  }
  else if (operations == UpdateOperations.Delete &&
    product.CreatedBy != Thread.CurrentPrincipal.Identity.Name)
  {
    Throw new DataServiceException(
      "Only records created by a user can be deleted by that user");
  }
}

この実装では、Product エンティティの CreatedBy プロパティへの依存度が高いため、データが作成された時点から後は、信頼できる方法で必ずこれが適用される必要があります。 図 6 では、追加操作用にクライアントから渡される値を上書きすることで、適用する方法を示しています。

この例が現在示しているように、UpdateOperations.Change 型の操作を処理することは問題にはなりません。 図 4 では、サービスは Products エンティティ セットに対して AllRead、WriteAppend (挿入)、および WriteDelete の操作の実行しか許可しないように構成されていました。 したがって、このエンドポイントでは Product エンティティの変更要求はサービスによって直ちに拒否されるため、ChangeInterceptor が変更操作に対して呼び出されることはありません。 更新を可能にするには、図 4 の SetEntitySetAccessRule への呼び出しに、WriteMerge か WriteReplace、またはその両方を設定する必要があります。

ドメイン間の承認

Silverlight プラグインでは、ドメイン間の HTTP 要求が可能です。 ドメイン間呼び出しは、Silverlight アプリケーションがダウンロードされたドメイン以外のドメインに対する HTTP 要求です。 このような呼び出しができることは、従来、セキュリティの脆弱性であると見なされていました。 悪意のある開発者が他のサイト (オンライン バンキング サイトなど) に要求を行い、そのドメインに関連付けられている Cookie を自動的に転送できるためです。 潜在的に、同じブラウザー プロセス内の別のログイン セッションへのアクセスを攻撃者に許可する可能性があります。

このため、サイトでは、ドメイン間ポリシー ファイルを配置して、ドメイン間呼び出しを許可するかどうかを選択できるようにする必要があります。 ドメイン間ポリシー ファイルは、許可されるドメイン間呼び出しの種類を記述した XML ファイルです (たとえば、呼び出し元のドメインと呼び出し先の URL などを定義します)。 詳細については、「ドメインの境界を越えてサービスを利用できるようにする」(msdn.microsoft.com/library/cc197955(VS.95)) を参照してください。

ドメイン間呼び出しに対する機密情報の公開は、必ず十分に注意して行ってください。 ただし、認証と併せてこのような公開をサポートする必要があると判断した場合は、前述のフォーム認証など、Cookie ベースの認証方法は不適切です。 代わりに、メッセージ資格情報の利用を検討してください。メッセージ資格情報では、ユーザー名とパスワードがサーバーに渡され、呼び出しごとに検証されます。 WCF では、TransportWithMessageCredential セキュリティ モードによって、メッセージ資格情報がサポートされます。 詳細については、「方法: Silverlight アプリケーションでサービスの保護にメッセージ資格情報を使用する」(msdn.microsoft.com/library/dd833059(VS.95)) を参照してください。

もちろん、この方法では認証プロセスから ASP.NET が完全に排除されるため、前述の ASP.NET による承認と併せて利用することは困難です。

Silverlight XAP ファイルを保護する

Silverlight のセキュリティを気にかける方は、よく「XAP ファイルをどのようにして保護すればよいか」と質問されます。この質問の裏にある動機は、コードに含まれている知的財産の保護である場合があります。 この場合、コードを理解しにくくする処理を検討する必要があります。

また別の一般的動機として、悪意のあるユーザーがコードを解析して Silverlight アプリケーションの動作を理解することで、サービスに不正にアクセスする可能性を防ぐことも挙げられます。

通常、私は、この質問に対して 2 つのポイントをお伝えします。 1 つは、Silverlight アプリケーション (.xap ファイル) のダウンロードを認証および承認済みのユーザーに制限することはできますが、このようなユーザーが未承認のユーザーよりも悪意がないと信頼できる根拠はないということです。 アプリケーションがクライアントにダウンロードされたら、ユーザーがコードを解析して、自分の特権の昇格や第三者へのライブラリの転送を図ることを防ぐ手立ては絶対にありません。 コードをわかりにくくすることで、このような処理を多少難しくすることはできますが、アプリケーションを保護するには十分な対策とはいえません。

2 つ目は、Silverlight アプリケーションから正規にサービスの呼び出しを実行できるユーザーは、たとえば、インターネット ブラウザーやなんらかの JavaScript を使用して、サービスを直接呼び出せることに留意する必要があるということです。 これを防ぐ手段はないため、セキュリティ対策としては、サービスのセキュリティ強化に注力することが最も重要です。 適切にサービスのセキュリティを強化できれば、悪意のあるユーザーが Silverlight アプリケーションのコードを入手しても問題になりません。 それでも、認証済みユーザーしか .xap ファイルにアクセスできないようにすることを希望する方もいます。 これは可能ですが、使用中の IIS のバージョンと選択した認証方法によって、実装の難易度は変わります。

Windows 認証を使用している場合は、IIS ディレクトリ セキュリティを使用して簡単に .xap を保護できます。 ただし、フォーム認証を使用している場合は、処理がもう少し複雑になります。 この場合、要求に保持されている Cookie を FormsAuthenticationModule によってインターセプトし、検証することで、要求されたリソースへのアクセスを許可または拒否します。

FormsAuthenticationModule は ASP.NET モジュールであるため、この検証を実行するには、要求が ASP.NET パイプラインを通過する必要があります。 IIS6 (Windows Server 2003) 以前のバージョンでは、.xap ファイルに対する要求は、既定では ASP.NET を経由しません。

ただし、IIS7 (Windows Server 2008) では、統合パイプラインが導入されており、すべての要求を ASP.NET パイプラインを経由させることができます。 配置先が IIS7 であり、統合パイプライン モードで実行しているアプリケーション プールを使用する場合は、.xap files の保護は、前の「ASP.NET での承認」で説明した .svc ファイルの保護よりも難しいことはありません。 ただし、配置先が IIS6 以前の場合は、おそらく追加の作業が必要になります。

一般的な方法の 1 つでは、ASP.NET パイプラインによって処理される別の拡張機能を利用して、.xap ファイルを構成するバイトをストリーミングします。 この場合、通常は、IHttpHandler 実装 (.ashx ファイル) を利用します。 詳細については、「HTTP ハンドラの概要」(msdn.microsoft.com/library/ms227675(VS.80)) を参照してください。

また別の方法としては、IIS の構成を変更して、.xap ファイルが ASP.NET パイプラインを経由するようにします。 ただし、この場合は IIS 構成を大幅に変更することになるため、前述の方法を採用することが多くなります。

フォーム認証で注意が必要なもう 1 つの問題は、ログイン画面です。 この記事での前述の提案のように、ASP.NET Web フォームを使用しないことを選択できれば、問題はありません。 しかし、Silverlight でログイン画面を作成する場合は、アプリケーションを複数の部分に分割する必要があります。 ある部分 (ログイン モジュール) は未認証ユーザーが利用できるようし、別の部分 (保護されたアプリケーション) は認証済みユーザーのみが利用できるようにします。

これには、次の 2 とおりの方法があります。

  1. 2 つの Silverlight アプリケーションを個別に用意します。 1 つにはログイン ダイアログを組み込み、サイト内のセキュリティ保護されていない領域に配置します。 ログインに成功すると、サイト内のセキュリティ保護されている領域にある .xap ファイルを指定するページにリダイレクトされます。
  2. アプリケーションを 2 つ以上のモジュールに分割します。 サイト内のセキュリティ保護されていない領域にある最初の .xap により、認証処理を実行します。 認証に成功すると、それ以降は、この .xap によって、Silverlight アプリケーションに動的に読み込むことができる、セキュリティで保護された領域から .xap を要求します。 この方法については、最近ブログ (thejoyofcode.com/How_to_download_and_crack_a_Xap_in_Silverlight.aspx、英語) で紹介しています。

Josh Twist は、英国のマイクロソフト アプリケーション開発コンサルティング チームの主任コンサルタントです。彼のブログは thejoyofcode.com (英語) です。

この記事のレビューに協力してくれた技術スタッフの Zulfiqar Ahmed、Chris Barker、および Simon Ince に心より感謝いたします。