CodeZine(コードジン)

特集ページ一覧

ASP.NETを利用した共有リソースへのアクセス方法

COM+のサービスを利用するサービスコンポーネントの作成

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2005/08/09 12:00

WebフォームやWebサービスの開発では、よく共有リソースへのアクセスが問題となります。本稿では、サービスコンポーネント(Enterprise Services)を作成して、共有リソースにアクセスする方法について解説します。

はじめに

 WebフォームやWebサービスの開発では、よく共有リソースへのアクセスが問題となります。多くのASP.NET開発者にとって、これはなかなかの難問です。Microsoft .NETでは、ユーザー認証とアクセス許可への新しいアプローチが採用されていて、プログラミング参考書や専門雑誌では一般に「セキュリティ」分野の事柄として扱われています。セキュリティ関連の論文や書籍では、フォーム認証の説明に大きなスペースが割かれていますが、最善の解決策を得るという観点からは、むしろASP.NETセキュリティのアーキテクチャを、IIS、ネットワーク、オペレーティングシステムのセキュリティとの関連で理解することが重要です。

 図1に示すのは、IISとASP.NETで提供される基本セキュリティです(図はMSDNのWebサイトより引用)。ASPセキュリティとは根本的に異なっています。ユーザーがWeb要求を出すと、次の一連のイベントが発生します。

  1. ユーザーがHTTP要求を出します。
  2. 出されたWeb要求が、SYSTEMアカウントの下で動作しているIISに拾われます。SYSTEMアカウントは非常に強力なアカウントで、あらゆる種類の特権を持っています。IISは、選択された認証タイプに基づいて認証を行い、認証されたユーザーごとにアクセストークンを作成します。たとえば、匿名認証が選択されていれば、匿名ユーザーのアクセストークンを作成します(既定ではIUSR_MACHINE)。また、設定されているアクセス許可タイプに基づいてアクセス許可も実行します。たとえば、特定IPアドレスからしか要求を受け付けないようにIISを設定することができます。
  3. 認証されたユーザーの要求とWindowsアクセストークンが、IISから「aspnet_isepi.dll」に引き渡されます。「aspnet_isepi.dll」は.aspx URLを扱うISAPI拡張機能を備えたIISモジュールで、IISとASP.NETランタイム環境をつなぐブリッジとして働きます。要求は、名前付きパイプ経由でワーカープロセスに送られます。
  4. ワーカープロセスは「aspnet_wp.exe」であり、ここにCLRが存在します。このワーカープロセスは、既定ではASPNETアカウントの下で動作します。ASPNETアカウントは、ASP.NETフレームワークのインストール時に作成されるローカルアカウントで、SYSTEMアカウントがきわめて強力であるのと異なり、少数の特権しか持っていません。ASP.NETは、独自の認証設定に基づいてユーザー認証を行います。たとえば、設定がWindows認証になっていれば、IISからのトークンをすべて受け入れます(追加の認証はありません)。また、要求されたリソースやファイルごとにアクセス許可を判断できます。たとえば、FileAuthorizationModelを使用すれば、要求を出したユーザーに当該リソースへのアクセス権限があるかどうかを検査できます。Windows認証では、ユーザーのアクセストークンがACLと比較されます。
  5. ここまで順調に進むと、アプリケーションが特定IDの下でリソースにアクセスします。既定では、ASPNETプロセスアカウントの与えるIDが使用されますが、偽装が有効になっているときは、当該ユーザーの本来のIDを使用するほかに、別のIDの下でアプリケーションを実行するという偽装設定もできます。

 セキュリティがクリアされれば、いよいよデータにアクセスできます。しかし、いまネットワークリソースに対してNTFSアクセス許可が設定されているとすると、先へ進む前に必ずやっておかなければならない作業が2つあります。1つは、ASP.NETを用いてUNC(汎用命名規則)シェア上のファイルとフォルダにアクセスする(つまり、ネットワーク上の共有ファイル/フォルダにアクセスする)タスクを指定することです。もう1つは、リソースアクセスに使用するIDを選択することです。まず2番目の作業を完了しておかないと、最初の作業も実行できません。

 ネットワークリソースにアクセスする方法はいくつかあります。

  • ASP.NETプロセスIDを使用する
  • 匿名ユーザーアカウントを使用する
  • LogonUser APIを使用する
  • サービスコンポーネント(Enterprise Services)を使用する

 ASP.NETプロセスIDを使用する方法には明らかな欠点があります。というのは、この方法で与えられるIDは、既定では、アプリケーションがリソースへのアクセスを試みたときのID(ASPNET)となるからです。簡単な解決方法として、ローカルアカウントを作成し、そのユーザー名とパスワードをリモートコンピュータ上のそれに一致させるやり方がありますが、ほとんどの企業は大規模なイントラネット環境を取り入れていますから、実際的な方法とは言えません。また、誰がどのリソースにアクセスするのかを知っておくことも重要でしょう。この方法でも、ネットワークリソースへのアクセスを実現することはできますが、実に非効率的です。

 2番目の方法では、匿名ユーザーアカウント(たとえばIUSR_MACHINE)を使用します。しかし、最初の方法と同じ理由から、この方法も非効率的であるのは明らかでしょう。

 3番目は、LogonUser APIを使用する方法です。ここではWin32 LogonUser APIを呼んで、特定のIDを偽装します。また、ASP.NETプロジェクトの「web.config」ファイルで<identity>エレメントを設定しておく偽装方法もあります。ただ、MSDNの記事によると、「これらのやり方は推奨できません。この方法だと、必然的に、<オペレーティングシステムの一部として動作する>権限をASP.NETプロセスアカウントに与えることになってしまい、Webアプリケーションのセキュリティが大幅に低下します」。したがって、理想的なアプローチとはとうてい言えません。

 最後の(そして、選択可能な唯一の)オプションは、あるサービスコンポーネントを固定IDとして動作するよう設定し、ネットワークリソースにアクセスさせるという方法です。一見たいへんそうなやり方ですが、断然すぐれた方法でもあります。この方法のアーキテクチャを次の図に示しておきます。

 J. D. Meierらが発表したセキュリティ論文によると、Enterprise Servicesサーバーアプリケーションでプロセス外サービスコンポーネントを使う方法には、次の利点があります。

  • 使用するIDを柔軟に設定でき、ASP.NETのIDに依存せずに済みます。
  • トラステッド(高度の特権を持つ)コードをメインのWebアプリケーションから分離できます。
  • プロセスホップが1つ増え、飛び越すべきセキュリティバーが高くなります。特権が高度になることで、攻撃者にとっては、プロセス境界を越えてプロセスに入り込むことがずっと難しくなります。
  • LogonUser APIコールを使い、手作業で偽装する必要があるときも、メインのWebアプリケーションから切り離されたプロセスでそれを実行できます。

サービスコンポーネントの作成

 COM+からサービスを受けるアセンブリをサービスコンポーネントと呼びます。サービスコンポーネントの作成には、COM+技術に精通し、十分な経験を積んでいることが要求されます。COM+アプリケーションはユーザーインターフェイスを含んでおらず、その点で伝統的な意味でのアプリケーションとは異なります。むしろ、アプリケーションを構成しているコンポーネント群のコンテナであり、COMと.NETアセンブリDLLがそのアプリケーションのビジネスロジック部分を受け持ちます。COM+は、COMの新版でも、COMとDCOMを組み合わせたものでもなく、MTS(Microsoft Transaction Services)を継承する技術です。COM+サービスを使用できるのは.NETコンポーネントであり、それをEnterprise Servicesと呼んでいます。これの実装は中間層.NETコンポーネントと同様ですが、いくつか新しい点があります。

 サービスコンポーネントの作成手順を以下に示します。

  1. 新しいクラスライブラリプロジェクトを作成します。目的は、Webアプリケーションの初期クラスライブラリとなる中間層コンポーネントを構築することです。
  2. 適切なクラス、メソッド、プロパティを追加します。ファイルとフォルダにアクセスするので、System.IO名前空間のインポートが必要です。
  3. 図3 クラスライブラリ
    図3 クラスライブラリ
  4. Webフォームアプリケーションを作成します。
  5. 図4 Webフォームアプリケーション
    図4 Webフォームアプリケーション
    これでコンポーネント(まだサービスコンポーネントではありません)をテストできます。Enterprise Servicesアプリケーションで有意義なセキュリティを実現するには、Windows認証を使って偽装を有効にしなければなりません。この作業は、Webアプリケーションの「web.config」ファイルで行います。これにより、サービスコンポーネントは元の(要求を出した)ユーザーを認証し、そのユーザーのIDに基づいてアクセス許可の決定を下すことができます。開発途中、コンポーネントがまだサービスコンポーネントでない間は、これで共有ファイル/フォルダへの十分なアクセスセキュリティを実現できます。
    <authentication mode="Window" />
    <identity impersonate="true" />
    
    テストするには、まずクラスをコンパイルし、このオブジェクトへの参照をWebアプリケーションに追加します。次に、クラスを以下のとおり初期化します。
    Dim objEnterprise As New AccessingSharedResources.dal_AccessNetwork()
    
  6. 強い名前を持つアセンブリを作成します。
    • Visual Studio .NETコマンドプロンプトを実行します([スタート]→[プログラム]→[Microsoft Visual Studio .NET]→[Visual Studio .NET Tools]→[Visual Studio .NET Command Prompt]を選択)。
    • プロジェクトディレクトリへ移動し、「sn -k KeyPair.snk」というコマンドを入力します。
    • これにより公開鍵/秘密鍵のペアが作成されます。これらの鍵は、Visual Studio .NET IDEでコンポーネントに強い名前を与えるために使用されます。このとき、プロジェクトディレクトリに「KeyPair.snk」ファイルが作成されることに注意してください。
    • 「AssemblyInfo.vb」ファイルのコードウィンドウを開き、<Assembly: AssemblyKeyFile("KeyPair.snk")>というアセンブリ属性を追加します。
    • プロジェクトをコンパイルすると、強い名前を持つアセンブリが作成されます。
  7. オブジェクトをGAC(Global Assembly Cache)に追加します。
    • .NET Framework Configuration Toolを開きます([スタート]→[プログラム]→[Administrative Tools]→[Microsoft .NET Framework Configuration]を選択)。
    • [Assembly Cache]→[View List of Assemblies in the Assembly Cache]を選択して、GACにあるすべてのアセンブリを表示します。
    • [Assembly Cache]アイコンを右クリックし、[追加]を選択します。
    • プロジェクトの「bin」ディレクトリにある「AccessingSharedResources.dll」ファイルを探し、それをダブルクリックします。
 コマンドプロンプトで「gacutil /i AccessingSharedResources.dll」と入力しても、オブジェクトをGACに追加できます。これがもう1つの追加方法です。
  1. 「System.EnterpiseServices.dll」への参照を追加します。
  2. 次のように記述し、必要なEnterprise Services名前空間をインポートします。
    • Imports System.EnterpriseServices
    • Imports System.Runtime.CompilerServices
    • Imports System.Reflection
  3. 各クラスがServicedComponentクラスを継承するようにします。
  4. Public Class dal_AccessNetwork
        Inherits ServicedComponent
    
  5. サービスコンポーネント関連のアセンブリ属性を、サービスコンポーネントをサポートする「AssemblyInfo.vb」ファイルに追加します。
    • System.EnterpriseServices名前空間をインポートします。
    • 次を追加します。
    • 'COM+ Application Name
      < Assembly: ApplicationName("AccessingSharedResources")>
      'COM+ Activation Type (Server which is out-of-process)
      <Assembly: ApplicationActivation(ActivationOption.Server)>
      
  6. AssemblyVersionを設定します。
  7. 新規プロジェクトの作成時にMicrosoft Visual Studio® .NET開発システムが生成するAssemblyVersionは、既定では<Assembly: AssemblyVersion("1.0.*")>となります。MSDNの記事によると、プロジェクトを再構築すると、そのたびに新しいアセンブリバージョンが生成されますし、サービスコンポーネントクラスを指し示すためのクラスID(CLSID)も新しくなります。したがって、「Regsvcs.exe」を用いてアセンブリをコンポーネントサービスに繰り返し登録すると、CLSIDだけが異なる重複コンポーネント(クラスのみ)が「Components」フォルダにいくつも現れます。
    これは厳密なCOMバージョン規則に従っており、既存の管理下/管理外クライアントの破壊を防ぎますが、開発中には目障りになることも確かです。したがって、開発とテストの段階では、アセンブリレベルのAssemblyVersion属性を用いて、明示的なバージョン設定を行うことを考えてもよいでしょう。たとえば、
    <Assembly: AssemblyVersion("1.0.0.1")>
    
    これで、連続するプロジェクト構築ごとに新しいCLSIDが発生することを阻止できます。
    この時点でプロジェクトを再構築(コンパイル)します。コンポーネントはまだプロセス内ですから、これをプロセス外にしなければなりません。引き続き以降の手順を行ってください。
  8. 新しいCOM+アプリケーションを作成し、そこにアセンブリを登録します。
    • Visual Studio .NETコマンドプロンプトを実行します(ステップ4を参照)。
    • dllのある場所(「bin」ディレクトリの下です)に移動します。
    • 「regsvcs /c AccessingSharedResources.dll」と入力して、[Enter]キーを押します。
  9. Webアプリケーションを手直しします。
    • 「System.EnterrpiseServices.dll」への参照を追加します。
    • Imports System.EnterpriseServices文をWebクライアントに追加します。

 これでEnterprise Servicesコンポーネント(別名サービスコンポーネント)が完成しました。このコンポーネントをCOM+アプリケーションとして表示します。

  • Component Services Managerを実行します([スタート]→[プログラム]→[Administrative Tools]→[Component Services]を選択)。
  • [Console Root]→[Component Services]→[Computers]→[My Computer]→[COM+ Applications]→[AccessingSharedResources]→[Components]と展開します。
図5 Component Services Manager
図5 Component Services Manager

メリットとデメリット

 サービスコンポーネントを使用することのメリットは次のとおりです。

  • IDを柔軟に使用でき、ASP.NETのIDに依存せずに済みます。
  • トラステッド(高度の特権を持つ)コードをメインのWebアプリケーションから分離できます。
  • プロセスホップが1つ増え、飛び越すべきセキュリティバーが高くなります。特権が高度になることで、攻撃者にとっては、プロセス境界を越えてプロセスに入り込むことがずっと難しくなります。
  • LogonUser APIコールを使い、手作業で偽装する必要があるときも、メインのWebアプリケーションから切り離されたプロセスでそれを実行できます。

 デメリットは次のとおりです。

  • サービスコンポーネントの呼び出しは、ネイティブの.NETオブジェクトを呼ぶときほど速くなく、アプリケーションのパフォーマンスに悪影響があります。
  • ステップ数とコード量が増えます。
  • ネイティブの.NETコンポーネントよりも管理が困難です。
  • COM+アプリケーションにDLLをインストールする必要があります。

まとめ

 COM+の基本機能とも言うべきオブジェクトプーリング、トランザクションサポート、同期化、JITA(Just-In-Time Activation)、イベント追跡などを使用せずに、目標を達成できました。COM+の諸機能はいずれも高度であり、現実に使用するには深い理解が必要です。しかし、ネットワーク上の共有リソースにアクセスするだけならば、ネイティブの.NETクラスをCOM+アプリケーションにインストールし、COM+固有のコードを数行追加するだけで済みます。

参考資料



  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • Anthony Arslan(Anthony Arslan)

    現在、開発者としてネブラスカ州リンカンの大手金融機関に勤務するかたわら、地元の大学で「Microsoftアプリケーション」という授業を受け持っている。コンピュータ科学修士。連絡先はarslan@nefel.com。

  • japan.internet.com(ジャパンインターネットコム)

    japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.com や EarthWeb.c...

バックナンバー

連載:japan.internet.com翻訳記事

もっと読む

All contents copyright © 2005-2020 Shoeisha Co., Ltd. All rights reserved. ver.1.5