第 3 章 セキュリティ、運用管理、通信のポリシー
November 2002
日本語版最終更新日 2003 年 3 月 17 日
概要
: 例外管理や認定など、アプリケーション全体に影響を与える設計上の問題を詳細に説明します。
ポリシーとは組織が定める一連の規則のことを言いますが、具体的には、アプリケーションのセキュリティをどのように確保するか、アプリケーションをどのように管理するか、アプリケーションの各コンポーネントがお互いにどのように通信するか、外部のサービスとどのように通信するかなどについて規定します。アプリケーションまたはサービスの各層の設計は、ポリシーによって変わってきます。図 3.1 を参照してください。
図
3.1
組織が定めるポリシーとアプリケーションの設計の関係
ポリシーは組織単位で策定することが一般的ですが、部署ごとに定めることもできます。"ゾーン" という考え方が有効な場合もあります。アプリケーション、サービス、またはアプリケーションの各層が同一のポリシー サブセットを共有している場合は、1 つのゾーンに属していると考えます。たとえば、インターネットに公開するデータ センターの場合、社内のインフラストラクチャとは異なるポリシー セットが必要となります。アプリケーションの他の部分と比べて厳しくセキュリティを設定した特別なゾーンを設けるのです。この場合、データ センター内のアプリケーションとサービスのゾーンは、イントラネット内のアプリケーションとサービスのゾーンとは異なります。コンポーネントの適切な展開先を決めるには、適用されるポリシーを十分に理解し、これに応じて実行環境となるゾーンを定義することが重要です。
このドキュメントは、「.NET のアプリケーション アーキテクチャ : アプリケーションとサービスの設計」の第 3 章です。このガイドの概要は、「第 1 章 はじめに」を参照してください。
この章の内容
この章は、以下の節で構成されています。
セキュリティ ポリシーの設計
セキュリティ ポリシーの設計にあたっては、認証、承認、通信のセキュリティ保護、監査、およびプロファイル管理について考慮することが必要です。その構造を図 3.2 に示します。
図
3.2
セキュリティ
ポリシーの各要素
セキュリティの基本原則
セキュリティ ポリシーを設計するときは、セキュリティの基本原則について理解しておく必要があります。以下にその一部を示します。
-
できる限り、独自にセキュリティ ソリューションを構築することは避け、検証済みで実績あるセキュリティ システムを導入してください。業界での実績が確認されているアルゴリズム、手法、プラットフォームが提供するインフラストラクチャ、ベンダにより検証済みでサポートを受けられるテクノロジを採用してください。独自のセキュリティ インフラストラクチャを開発する場合は、監査とセキュリティの専門企業にも協力を仰ぎ、方法論と具体的な手法について実装の前後に検証を行ってください。
-
外部入力は、必ず疑ってください。ユーザーが入力したデータや他のサービスが送信したデータは、検証が必要です。
-
外部システムは、セキュリティ保護されていないものと考えてください。外部システムから送信された機密データが暗号化されていない場合、データは改ざんされた可能性があるものとして扱う必要があります。
-
最低限の特権の原則を貫くことが重要です。サービス アカウントの属性は、アプリケーションで最低限必要となる範囲でだけ有効にしてください。また、リソースにアクセスするときも、必要最低限のアクセス許可だけを持ったアカウントを使用してください。
-
露出部分を少なくすることも重要です。アプリケーションを通じて公開されるコンポーネントの数やデータの量が多くなると、それだけセキュリティ リスクは増大します。公開する必要がある機能だけを公開してください。
-
セキュリティ保護を標準としてください。明示的に必要とされるサービス、アカウント権限、テクノロジを除いては、すべてを無効にします。アプリケーションをクライアント コンピュータやサーバー コンピュータに展開するときは、セキュリティ保護された状態が既定の構成となるようにしてください。
-
秘匿情報に依存することは避けてください。データを暗号化することは、鍵を使用し、実績ある暗号化アルゴリズムを使うことを意味します。セキュリティ保護されたデータ ストレージを使用すると、どのような状況下でも不正なアクセスを防ぐことができます。文字列を複雑化したり、秘匿のファイル パスに情報を保存したりすることはセキュリティと呼びません。
-
STRIDE の原則に従ってください。STRIDE とは、Spoofing、Tampering、Repudiability、Information disclosure、Denial of service、Elevation of privileges の略で、それぞれ、"なりすまし"、"改ざん"、"否認"、"情報の漏洩"、"サービス拒否"、"特権の引き上げ" を意味します。これらは、システムが自己防衛する必要のあるセキュリティ脆弱性の分類を表したものです。STRIDE の詳細については、MSDN ライブラリの「セキュリティ性を考慮したデザイン」を参照してください。
-
ゲートでのチェックを心がけてください。つまり、ユーザーの承認を実行する場所から後はプロセスが進むことができないようにします。
-
内外を問わずにシステムをロックダウンしてください。内部のユーザーやオペレータも、外部のハッカーと同等以上の脅威となるためです。
認証
認証とは、セキュリティ保護された形で身元確認することを言います。具体的には、アプリケーションのセキュリティ要件に従ってユーザーの身元を安全に確認するメカニズムのことを意味します。
認証は、ユーザー インターフェイス層に実装する必要があります。承認、監査、パーソナライゼーションなどの機能は、認証を基盤として実現することになります。基本的に、ユーザーは資格情報 (ユーザー名とパスワードなど) を入力することによって身元を証明します。資格情報には他に、バイオメトリック テクノロジ、スマートカード、物理的な鍵、デジタル証明書などがあります。
アプリケーションをサービスとして公開する場合は、決まったサービス インターフェイスで認証を実行し、サービスの提供先が信頼済みの既知のパートナーであることを確認し、関係のない外部サービスが呼び出し元を偽るなりすましを行っていないことをチェックしてください。
メモ Microsoft® ASP.NET を使用して呼び出し元を認証する方法の詳細については、MSDN ライブラリの「ASP.NET における認証 : .NET セキュリティ ガイド」を参照してください。
ビジネス ロジックを設計するときは、認証プロセスへの依存度をできる限り排除してください。ビジネス ロジックで特に必要がない限りは、ユーザー情報を渡すだけのパラメータをコンポーネントのメソッドに追加することは避けてください。
層をまたがる ID のフロー
機能の場所がユーザーから論理的に離れれば離れるほど、その機能がユーザーの ID 情報に依存する度合いは小さくなります。サービス ベースのソリューションの場合、ユーザー以外の手によって処理が呼び出されることもあります。ユーザー インターフェイスから論理的に離れた場所の処理では、呼び出し元のユーザーへの依存度を小さくすることを心がけてください。
承認や監査を実行するには、呼び出し元 (ユーザーまたはサービス) の ID 情報をアプリケーションの各層に引き渡すことが必要になることもあります。これは、呼び出し元のユーザーまたはサービスの ID、アプリケーション層のサービス アカウントのいずれかとなります。ID のフローを実現するには、通信メカニズムにセキュリティ コンテキストのフローを処理させるか、トークンやアプリケーション チケットを引き渡すか、ユーザーの ID または資格情報を引き渡します。通信メカニズムにセキュリティ コントロールのフローを処理させる場合は、たとえば、DCOM リモート処理による Kerberos 委任を使用できます。
以下の各シナリオごとに考えてみましょう。
-
呼び出し元と呼び出し先のアプリケーションがプラットフォームのセキュリティ サブシステムを共有していない。または、共通の認証メカニズムを共有していない。この場合、既存のセキュリティ コンテキストを引き渡すことはできません。必要な資格情報を渡すことによって認証を再度実行する必要があります。
-
呼び出し元と呼び出し先のアプリケーションの両方が信頼済みの Microsoft Windows® ドメイン内に存在する。または、アプリケーションが Windows の ID に基づいて承認を実行するか、Microsoft .NET Enterprise Services のロールを使用している。この場合は、Kerberos チケットまたは NTLM トークンを引き渡すことのできる通信メカニズムを採用する必要があります。DCOM-RPC にはこの機能があります。チャネルが提供する情報を使用すると、独自にプリンシパルを作り直して、これを認証情報を基にスレッドに関連付けることができます。NTLM トークンを認証に使用できるのは、1 ネットワーク ホップに限られます。また、Kerberos 委任を使用するには、コンピュータ、ユーザー、ドメインのレベルでポリシー設定が必要になります。詳細については、後の「通信ポリシーの設計」、または以下のドキュメントを参照してください。
-
呼び出し元と呼び出し先のアプリケーションが、シングル サインオン ソリューションやユーザー認証の機能を持つ一元管理型の Web サービスなど、Windows 以外の認証メカニズムを共有している。 この場合は、認証サービスが提供するトークンを引き渡します。トークンは、SOAP ヘッダーなど、帯域外のメカニズムを使用して引き渡します。関数パラメータは使用しません。認証メカニズムは、有効なトークンの提示を受けてユーザーを認証します。つまり、認証するトークンと元のコンピュータは関連付けられません。特に長時間にわたるトランザクションでは、トークンの認証に十分な時間を許容してください。トークンの生成には、多くの場合、ユーザーの資格情報と salt 値のハッシュが使われます。salt 値の定義については、MSDN ライブラリの「Security Glossary」(英語情報) を参照してください。
-
呼び出し元と呼び出し先のアプリケーションが同じコンテキストの中で実行している。 この場合は、Microsoft .NET が呼び出しを処理し、スレッドに関連付けられている既存の CurrentPrincipal オブジェクトは維持されます。AppDomain が同一の場合、およびライブラリ アクティベーションを使用して Enterprise Services ベースのアプリケーションを呼び出す場合は、これに該当します。
他のサービスを使用した認証
アプリケーションがユーザーの代理となって他のサービスを呼び出すケースを考えてみましょう。バックエンドにシングル サインオンのしくみを用意すると、ユーザーのトークン、資格情報を特定のサービス、特定のデータ ストアと対応付けることができます。たとえば、アプリケーションでは "Bob" の名前で認証されるユーザーが、別のレガシ データ ストアにアクセスするときは "Bobby" の名前を使用してログオンする場合もあります。ただし、アプリケーション (またはサービス) が他のデータ ストアやサービスにアクセスするときは、元のユーザーを偽装するのではなく、できる限りサービス アカウント (例 : "SalesApplication") を使用してください。組織が定めるセキュリティ要件が厳しい場合、この方法を採用できないことも考えられます。特に資格情報の管理が必要となる場合、アカウントのマッピング機能の開発は困難を極めます。ユーザー アカウントは常に同期された状態に置くことが必要になるからです。アカウント マッピングのメカニズムの中には、優れたしくみを持つものもあります。例えば、Microsoft Internet Information Services (IIS) を使用してクライアント証明書を Windows アカウントにマッピングするメカニズムなどがあります。
アプリケーションでユーザー アカウントを偽装する必要がある場合、そのプロセスは LogonUser を呼び出すことが必要になります。Windows 2000 では、プロセスのユーザー アカウントに "オペレーティング システムの一部として動作する" 権限が割り当てられている必要があります。これは、強力な権限であり、プロセスが侵害された場合、セキュリティ リスクの原因となります。ごく一部の例外を除き、ASP.NET または Enterprise Services をベースとするアプリケーションの ID に対してこの特権を割り当てることはできる限り避けてください。
独自の認証メカニズム
プラットフォームが提供する認証メカニズムもサードパーティの認証メカニズムもニーズに合わない場合は、独自の認証メカニズムを用意することの検討が必要です。独自の認証メカニズムを組み込むには、ユーザーのアカウント情報をどこかに保管し、渡された資格情報がシステムによって認証されたものかどうかをチェックするアルゴリズムを実装する必要があります。独自のユーザー認証のメカニズムを実装する場合は、以下のガイドラインを参考にしてください。
-
独自の Identity オブジェクトを使用してユーザー認証機能を実装してください。ユーザーの資格情報を引数に受け取るコンストラクタを作成し、結果に応じて IIdentity.IsAuthenticated の内部フラグを設定します。認証トークンを受け取るコンストラクタを作成することも 1 つの方法です。
-
ユーザーのパスワードをそのままの状態で保管することは避けてください。データベースには、ユーザーの資格情報に salt 値を加えたものをハッシュ化したうえで格納してください。認証するときは、ユーザーが入力した資格情報に対して同じアルゴリズムを適用します。適用結果の文字列がデータベース内の文字列と一致した場合、そのユーザーが入力した資格情報は正しかったと判断できます。
-
監査を行い、認証の失敗を記録します。
-
特定のアプリケーション アセンブリ以外による Identity オブジェクトの作成と呼び出しを制限するには、StrongNameIdentityPermission 属性をメソッドに適用します。
-
認証トークンは Identity オブジェクトのプロパティとして公開してください。認証トークンは、ユーザー名に他の値を加えたデータを使ってハッシュ化します。トークンを使用できる場所を限定するには、コンピュータの名前や呼び出し元のアセンブリ名をハッシュの元データに含めます。トークンの有効期限を設定する場合は、タイムスタンプを含めます。ハッシュと暗号をどの程度複雑なものにするかは、トークンのセキュリティが破られたときに生じるリスクとのバランスで考えます。
プレゼンテーション層での認証
承認、監査、パーソナライゼーションをアプリケーションに組み込むには、ユーザー インターフェイス コンポーネントでユーザー認証を行う必要があります。Web ベースのインターフェイスの場合、認証メカニズムの選択肢は多数あります。諸条件に適した認証メカニズムを選択する方法については、MSDN ライブラリの「ASP.NET における認証 : .NET セキュリティ ガイド」を参照してください。ASP.NET ベースのアプリケーションの場合、現在のプリンシパルが Global.asax の OnAuthenticate イベントで設定されます。
Windows ベースのユーザー インターフェイスの場合は、独自の認証メカニズムを採用するか、Windows ログオンに基づいてユーザーを認証します。前者の場合は、ユーザー名とパスワードの入力を求めるしくみをアプリケーションに実装します。具体的には、ログオン用のユーザー インターフェイスを作成し、必要な情報を持った Principal オブジェクトをメインのスレッドとアプリケーションが作成するすべてのスレッドに対して設定します。
ユーザー プロセス コンポーネントでは認証を行いません。前に述べたのとおり、アプリケーションの起動時に設定されるセキュリティ コンテキストを使用します。ASP.NET ベースのアプリケーションの場合は、OnAuthenticate イベントで設定されます。
ユーザー プロセス コンポーネントは原則として、ユーザー インターフェイス コンポーネントと同じユーザー コンテキストで実行します。必要な認証処理は、ユーザー インターフェイスまたはレンダリング インフラストラクチャに委任します。ASP.NET の場合、ASPX ページに対する要求があると、IIS により認証資格情報が要求されるか、ASP.NET によりフォーム ベースの認証ページにリダイレクトされます。この処理は、ユーザー プロセス層には透過的に処理され、ステート フローが割り込まれることはありません。認証済みセッションの有効期限が切れ、再度の確立が必要な場合も同様です。
ビジネス コンポーネントでの認証
ビジネス コンポーネントでは必ず呼び出し元を認証するか、認証をサービス インターフェイスに委任する必要があります。さまざまなコンポーネントが呼び出し元となりえます。次はその一例です。
呼び出し元の身元としては、次のようなユーザー、アカウントが考えられます。
ビジネス コンポーネントで呼び出し元を認証する場合は、これらの呼び出し元の身元をどのように認証し、その結果、どのような影響が承認処理に及ぶかを検討しておいてください。
データ アクセス コンポーネントでの認証
データ アクセス コンポーネントは、アプリケーションまたはサービス内の他のコンポーネントから呼び出されることを前提に設計するコンポーネントです。スクリプトや他のアプリケーションに対して公開することはないため、呼び出し元が設定したセキュリティ コンテキスト (スレッドの Principal オブジェクト)、またはリモート処理戦略の認証メカニズムに依存する形で問題ありません。
データ アクセス コンポーネントでデータベースとの認証を行うには、次のいずれかの方法を採用できます。
-
サービス アカウントを使用する
-
呼び出し元を偽装する
この場合は、ロールまたは特定のユーザーの種類に対応するサービス アカウントを使用します。複数のサービス アカウントを使用する場合は、その数を限定します。基本的には 1 つのサービス アカウントだけを使用しますが、きめ細かい承認が必要となる場合は複数のサービス アカウントを使用してもかまいません。注文処理アプリケーションの例では、データベースへのアクセスに "TheOrderApplication" アカウントを統一的に使用することや、呼び出し元のユーザーのロールに応じて "OrderProcessingManager" と "OrderProcessingClerk" の使い分けができるようにすることも考えられます。
次の状況に当てはまるときは、サービス アカウントを使用します。
-
BizTalk Server など、最初の呼び出し元を偽装できない環境からデータ ソースに接続する場合。
-
接続先システムのログオンに使用できるアカウントを変更できない場合。ログオン先がリレーショナル データベース管理システムの場合にこれが当てはまります。データベース管理者が厳格にアカウントを管理していることが多いためです。
-
インターネット経由でのログオンとなる Web サービスなど、アプリケーションの残りの部分とは異なる認証メカニズムがアクセス先のデータ ストアで採用されている場合。
-
データ ストアへのアクセスに多数のアカウントを使用すると、接続プーリングの効果が薄れ、パフォーマンスや拡張性の低下につながる場合。
次の状況に当てはまるときは、サービス アカウントの使用を避けてください。
-
サービスの資格情報を安全に格納、保守できない場合。
-
セキュリティ ポリシーの都合上、特定のユーザー リソースを使用してデータ ストアにアクセスする必要がある場合。ユーザーの代理として Microsoft SQL Server® のデータまたはオブジェクトにアクセスする場合などがこれに該当します。
-
データ ストアで処理内容の監査を実行していて、監査の記録を個々のユーザーに対応付ける必要がある場合。
アプリケーションのユーザー ベースと一対一に対応付けられるアカウント セットを使用してデータ ストアにアクセスする場合は、呼び出し元を偽装することになります。たとえば、"Joe" というユーザーがアプリケーションにログオンしたとします。このとき、データ アクセス コンポーネントが Joe の資格情報を使用してデータベースにログオンする場合、コンポーネントは "Joe" を偽装しているといいます。
次の状況に当てはまるときは、呼び出し元の偽装が必要となります。
呼び出し元の偽装には、通常、次の 2 つのメカニズムが使われます。
-
プラットフォーム偽装サービス。Windows 2000 以上では、Kerberos によるユーザーの偽装機能が用意されています。Web アプリケーションに Joe がアクセスしたとします。Windows 認証を使用している場合は、ネットワーク内でデータベースに至るまで一貫して Joe の偽装を行うことができます。
基本的に偽装の機能は、ネットワーク全体を通じて同一の認証メカニズムが採用されている場合、または Kerberos など互換性のある標準的な認証メカニズムが採用されている場合に限り、サポートされます。
Windows 2000 の場合、複数のネットワーク ホップをまたがってプラットフォームが提供する偽装レベルのことを "委任" と呼びます。セキュリティ コンテキストを委任できるようにするには、ドメイン、コンピュータ、およびユーザーのアカウントで委任を有効にする必要があります。Windows Server 2003 には、"強制委任" の機能があり、管理の柔軟性が強化されています。
-
バックエンドのシングル サインオン ソリューション。データ ソースのログオンに使うユーザーの資格情報 (ユーザー名とパスワードなど) を提供するメカニズムです。別のメカニズムによってユーザーを認証済みである証拠を提供すると、そのユーザーの資格情報が提供されます。このアプローチは、"弱い偽装" ということができます。通常は複数の論理ホップを伝播できないマッピングが必要となるためです。
分散型アプリケーションから SQL Server に接続する場合のガイドラインについては、MSDN ライブラリの「.NET データ アクセス アーキテクチャ ガイド」を参照してください。
メモ サービス エージェントに認証機能を実装する場合も、データ アクセス コンポーネントの場合と同様の内容が当てはまります。
ビジネス エンティティ コンポーネントでの認証
ビジネス エンティティ コンポーネントは、スクリプトや Microsoft Visual Basic® 開発システムからの利用を想定して、アプリケーションの SDK またはオブジェクト モデルの形で公開することもあります。
なお、他のアプリケーション コンポーネントやカスタム スクリプトからビジネス エンティティが呼び出されることがない場合は、認証の境界を設ける必要はありません。この場合は、現在のセキュリティ コンテキスト (現在のスレッドに関連付けられた Principal オブジェクト) を認証に使用してください。
ビジネス エンティティを公開して、カスタム スクリプトや他のアプリケーションから呼び出すことができるようにする場合は、プラットフォームによる認証メカニズムに依存することもできますが、これを使用しない場合は、追加のコンポーネントを用意し、クライアントがコードから "ログオン" してビジネス エンティティが要求するセキュリティ コンテキストを設定できるようにする必要があります。ビジネス プロセスによって非同期に開始されるなど、ビジネス エンティティが非偽装型のメカニズムによって呼び出される場合は、特定ユーザーの Windows セキュリティ コンテキストに依存する設計は避けてください。
承認
セキュリティ ポリシーのうち、認証された各セキュリティ プリンシパルに対してどのようなアクションを許可するかについては、"承認" で定義します。つまり、承認とは、だれに何を許可するかを規定するポリシーといえます。承認のポリシーを策定するときは、次の 2 点を特に考慮する必要があります。
-
ユーザーのアクセス許可と権限
-
コード アクセス セキュリティ
ユーザーのアクセス許可と権限とは、アプリケーションのコンテキストにおいてユーザー アカウントに何を許可するのかを示すものです。厳密にいうと、"アクセス許可" とは、リソース (ファイルやデータベース テーブルなど) に対して許可するアクションのことを意味し、"権限" とは、ユーザーに実行を許可するシステム タスク (システム時計の設定やコンピュータのシャットダウンなど) のことを意味します。ユーザーのアクセス許可と権限は、ユーザー単位で個別に設定することもできますが、複数のユーザーを論理的な単位であるグループやロールに分類した方が管理が簡単です。ほとんどのリソースは何らかの形でアクセス許可リスト (そのリソースに関して各ユーザーに割り当てるアクセス許可の一覧) を保持します。たとえば、Windows 環境の場合、リソースのセキュリティは、アクセス制御リスト (ACL) を通じて保護されます。ACL とは、そのリソースについて各セキュリティ プリンシパルに割り当てられているアクセス許可のリストであり、アクセス許可の具体的な内容もこれに保持されます。アクセス許可は、原則として累積されます。あるファイルに対して "読み取り" のアクセス許可を持つユーザーが、同じファイルに対して "変更" のアクセス許可を持つグループに所属している場合、このユーザーは "変更" のアクセス許可を持つことになります。この原則の例外は、"拒否" のアクセス許可が適用されているときです。リソースへのアクセスが明示的に拒否されているユーザーの場合、またはこのようなグループに所属しているユーザーの場合、他でどのようなアクセス許可が割り当てられていたとしても、ユーザーはリソースにアクセスできません。
コード アクセス セキュリティは、.NET で導入されたメカニズムです。これにより、高度なアクセス制御ができるようになり、セキュリティ構成の妥当性のクロス チェックもできるようになりました。コード アクセス セキュリティは、ユーザーのアクセス許可と権限とは異なり、アセンブリに対して何を許可するかを規定するものです。たとえば、ファイル システム リソースへのアクセスを特定のコードに対して拒否し、そのコードがアクセスしようとしたらアクセス違反例外をトリガするよう .NET アセンブリを構成することなどができます。また、信頼ゾーンを設定し、各種の要因に応じてアセンブリごとに異なるコード アクセス セキュリティ ポリシーを適用することもできます。
アクセス制御のメカニズムを設計するときは、次のマトリックスの内容を取り入れてください。
ユーザー アクセス セキュリティ
ユーザー アクセス セキュリティとは、現在の ID に対して何を許可するかを規定するものです。呼び出し元に何が許可されているかをチェックするには、さまざまな手法があります。ユーザー インターフェイスを持つアプリケーションの場合は、ビジネス ロジックが呼び出し元を偽装することもできますが、ユーザー インターフェイスを持たないバックエンド アプリケーションや特にサービスでは、通常、あらかじめ決められた "サービス" アカウントを使用します。
現在のプロセスの実行に使われている実際のアカウントを使用する代わりに、手動で独自の ID を実行中のスレッドに関連付けることもできます。この場合は、Principal オブジェクトを変更します。
ユーザーが環境およびプラットフォームに対して何を行うことができるかは、通常、ACL を通じて制御します。ACL は、現在のプロセスまたはスレッドの Windows ID と照合されます。Windows ID と照合されるリソースの代表的なものとしては、NTFS のファイル、システム API、.NET Enterprise Services (COM+) のコンポーネント、Windows 認証を使うよう構成されているサービスがあります。
Windows のグループ設定、ユーザー権限、セキュリティ管理の機能は充実しています。ただし、サービスによっては、Enterprise Services のロール ベースの承認など、独自の抽象化層を実装してもかまいません。たとえば、Enterprise Services では、ロールと照合する形で承認を行いますが、各ロールは実際には ACL と対応付けられています。
.NET では、ユーザー アクセス セキュリティについて、包括的かつ拡張性に優れた管理フレームワークが用意されています。これには、ID、アクセス許可のほか、プリンシパルとロールの概念も含まれます。
特定のロールのユーザーだけがメソッドを呼び出すことができるようにするには、以下のコード例のように、クラスのメソッドに対して必要な属性を適用します。
[PrincipalPermission(SecurityAction.Demand, role="Managers")]
public void PlaceOrder(DataSet Order)
{
// This code will not execute if the principal attached
// to the thread returns false when IsInRole is invoked
// with "Managers" as argument
}
詳細については、MSDN ライブラリに公開されている .NET Framework SDK の「PrincipalPermissionAttribute コンストラクタ」を参照してください。
作成したコンポーネントを Enterprise Services 環境に展開し、Windows を通じてユーザーを認証する場合は、次のコード例のように、Enterprise Services のロール管理機能を使用できます。
[SecurityRole("HelpDesk")]
public DataSet GetCancelledOrders(System.Guid CustomerID)
{ //... }
コンポーネントにリモートからアクセスする場合に、Enterprise Services のロール管理機能を使用するには、DCOM-RPC チャネルを通じてコンポーネントにアクセスする必要があります。
コード アクセス セキュリティ
コード アクセス セキュリティとは、アセンブリに対して何を許可するかを規定するものですが、アクセス元のコードに応じてアセンブリの実行を許可するかどうかを設定することもできます。たとえば、必要な特権を持っているユーザーが秘密裏にスクリプトを実行したとしても、スクリプトからオブジェクトを呼び出すことができないように設定できます。コード アクセス セキュリティのポリシーは、.NET リモート処理では適用されません。ポリシーのチェックは、同一アプリケーション ドメインから呼び出されたときに限り適用されます。
コードのアクセス許可は、次の情報に基づいてチェックできます。
-
アプリケーションのインストール ディレクトリ
-
アセンブリの暗号ハッシュ
-
アセンブリ発行者のデジタル署名
-
呼び出し元アセンブリのサイト
-
アセンブリの暗号厳密名
-
呼び出し元アセンブリの URL
-
呼び出し元アセンブリのゾーン
セキュリティ ポリシーは、組織全体、コンピュータ単位、ユーザー単位、またはアプリケーション単位で適用できます。.NET で定義されているゾーンは、インターネット、イントラネット、ローカル コンピュータ (MyComputer)、ゾーンなし (NoZone)、信頼済みサイト (Trusted)、制限付きサイト (Untrusted) の 6 つです。各ゾーンの詳細については、MSDN ライブラリの以下の資料を参照してください。
-
「コード アクセス セキュリティ」
-
「コード アクセス セキュリティの概要」
-
「SecurityZone 列挙体」
複雑な承認チェックの実装
場合によっては、複雑な承認チェックをアプリケーションで実行する必要もあります。注文処理アプリケーションの場合を考えてみましょう。複雑な条件の例としては、"呼び出し元のロールが Salesman であること、またはパートナーから呼び出されたサービスの場合は注文金額が 1,000 ドル以下であること、または呼び出し元のロールが Manager 以上の権限を持っていること" などが考えられます。このような承認ポリシーを実現するには、AND、OR、"以上"、"以下" を使用してアクセス許可を組み合わせると同時に、注文金額の値も知っている事が必要になります。このような承認チェックは、必要なコードをプログラミングによりアプリケーションに組み込む方が効率的です。純粋な規則の集合として切り離すには、多大な開発労力が必要となります。それほど条件が複雑でない場合は、属性や構成設定による宣言として承認ロジックを実装するなどの方法もあります。
アプリケーション レベルの独自承認スキームの設計
アプリケーションの承認の一部をオペレータではなくユーザーが管理し、承認関連のデータをデータベースなどの外部ストアに格納している場合は、独自の承認スキームを実装することが必要です。このような場合は、セキュリティ管理用のユーザー インターフェイスとロール メンバシップ管理用のデータベース スキーマをアプリケーションに組み込むことが一般的です。このようなフレームワークを開発するときは、以下のガイドラインを参考にしてください。
-
承認ロジックはすべて Principal オブジェクトを通じて公開する。Principal オブジェクトは、コンストラクタの引数に特定の ID を渡すことによって作成します。ID の IsAuthenticated プロパティをチェックし、ID の名前から該当する承認データを特定します。承認ロジックを IsInRole 関数を通じて公開すると、アプリケーションで PrincipalPermission 属性を使用でき、一貫した開発モデルを作り出すことができます。これにより、将来、別の認証スキーム、承認スキームが必要になった場合でも、スキームを変更できるようになります。この詳細については、MSDN ライブラリの「WindowsIdentity オブジェクトと WindowsPrincipal オブジェクトの作成」を参照してください。
-
承認データのストアとの通信に対して認証を実行する。承認データが格納されているストアのセキュリティを保護し、特定のアカウントだけが承認データの読み取りおよび書き込みを実行できるようにします。このようなデータ ストアにアプリケーションからアクセスするときは、読み取り専用のアカウントを使用し、データを書き換える必要がある部分でだけ、読み取りおよび書き込みのアクセス許可を使用してください。
-
Windows 認証を使用しない場合は、ユーザーの資格情報と認証識別子を承認データのスキーマから切り離す。承認データが内部的にユーザーを参照するところでは、できる限りプライベートな ID を使用します。これにより、将来必要になったときには認証スキームを変更することや、異なる認証メカニズムによるアプリケーションからも承認規則を呼び出すことができます。また、ユーザーが自分の ID を変更した場合にも対応できます。
-
パフォーマンスの強化が必要なときはキャッシュを使用する。プリンシパル オブジェクトの承認情報 (ロールのメンバシップなど) は、そのたびにストアにアクセスするのではなく、キャッシュに格納しておくことをお勧めします。承認データをキャッシュに格納する場合は、署名するかハッシュ化して、改ざんを防いでください。
-
常時接続できないクライアントがある場合は、オフライン機能を提供する。具体的には、クライアント自体に承認ロジックを埋め込むか、デジタル署名したコピーをローカルにキャッシュします。
-
承認データの格納ロジックをプラグ対応にする。フレームワークの設計を変えることなく、格納先の場所やアプリケーションを変更できるようになります。
-
他のアプリケーション アセンブリが Principal オブジェクトを作成できないようにするには、コード アクセスの呼び出し元アセンブリの属性として StrongNameIdentityPermission 属性を適用する。
メモ Windows Server 2003 では、新しい機能がいくつか追加されており、独自の承認機能を簡単に実装できるようになっています。
ユーザー、ロール、信頼済みのアプリケーションとサービス
アプリケーションやサービスどうしが対話する場合、それぞれがユーザー アカウントとロールの定義を管理しているケースが一般的です。組織全体でユーザーとグループが一貫して定義されている場合は例外ですが、このような場合であっても、対話先のサービスが定義するロールとユーザーに依存することは避け、自組織が定義するロールとユーザーを使うようにしてください。
サービスどうしの対話が必要になる場面では、できる限り、サービス単位で呼び出し元の認証と承認を行うことをお勧めします。たとえば、サービスがパートナー企業の別のサービスと対話する場合は、"Standard Partner"、"Premier Partner" などのロールを定義します。外部のサービスとパートナーの承認処理にロールを使用すると、将来パートナーの数が増えてアプリケーションを拡張する場合にも、コードや設計を見直す必要がないためです。
サービスどうしがユーザー アカウントを共有していて、ユーザー単位で承認を実行する必要がある場合は、交換するビジネス データの一部にユーザー情報を含める必要があります。ビジネス データが特定のユーザーから送信されたものかどうかを確認する必要がある場合は、認証トークンを付けるか、ドキュメントを署名して、送信元のユーザーまたはサービスが信頼済みであるかどうかを確認します。
システム境界でのセキュリティ コンテキストの設定
スレッドに割り当てられたカスタム プリンシパルは、プロセスやリモート処理チャネルを越えて引き渡されることはありません。したがって、基本的にシステムの境界では独自にセキュリティ システムを設定する必要があります。
現在のスレッドに対してカスタム プリンシパルを割り当てるには、次のことを行います。
-
資格情報、ユーザー トークン、ユーザー ID (または何らかの識別子) のいずれかをコンストラクタに渡すことによって必要な ID オブジェクトを作成します。独自実装による ID オブジェクトを使用する場合は、その ID が認証済みかどうかを表す内部フラグを持たせる必要があります。
-
ID オブジェクトのインスタンスをコンストラクタの引数として渡すことによって、プリンシパル オブジェクトを作成します。プリンシパル オブジェクトでは、Iprincipal:Identity が呼び出されたときに返すことができるように、引数に渡された ID オブジェクトを保持しておきます。
リモート処理チャネルに DCOM-RPC を使用していると、Windows のプリンシパルはリモート処理でも引き渡されます。
.NET の Principal オブジェクトと Identity オブジェクトの詳細、および独自の Windows プリンシパルでこのパターンを使用するコード サンプルについては、MSDN ライブラリの「プリンシパル オブジェクトと ID オブジェクト」を参照してください。
ユーザー インターフェイス コンポーネントでの承認
ユーザー インターフェイス コンポーネントは、ユーザーに対してデータを表示し、ユーザーからデータを収集する役割を担うコンポーネントです。次のような処理が必要となる場合は、このレベルで承認を実行します。
特定の情報をユーザーに見せることが望ましくない場合は、プレゼンテーション コンポーネント自体にその情報を渡さないことが、セキュリティ上最も安全といえます。
一般的には、基本となるユーザー インターフェイスやメニューに対して何らかのパーソナライゼーションのしくみを実装し、ユーザーのロールに応じて、表示するペイン、Web パーツ、メニュー項目を設定します。
通常、アプリケーションの起動には、ユーザー インターフェイスの .exe ファイルを使用します。ユーザー インターフェイス アセンブリ (またはユーザー インターフェイス アセンブリが呼び出すローカル コンポーネント) からファイルなどの機密リソースにアクセスできることが望ましくない場合は、ユーザー インターフェイス アセンブリに対してコードのアクセス許可を設定します。
アプリケーションのプレゼンテーション コンポーネントが実行される環境のセキュリティ コンテキストを確認し、適切な制限環境でテストを行ってください。
ユーザー プロセス コンポーネントでの承認
ユーザー プロセス コンポーネントとは、ユーザー プロセス間のデータと制御のフローを管理するコンポーネントです。次のような処理が必要となる場合は、このレベルで承認を実行します。
-
ユーザー インターフェイスとの対話プロセスの起動をユーザーに対して許可するかどうかを制御する。
-
実行しているユーザーに応じてユーザーとの対話の流れの中に含める "手順" またはユーザー インターフェイス コンポーネントを追加、削除する。たとえば、営業スタッフは自分が担当する地域のデータだけを閲覧できるとします。この場合は、営業報告書作成のウィザードの手順の中に、地域選択の画面を含める必要はありません。
理想的には、親ダイアログ ボックスに必要な機能を実装し、別のダイアログ ボックスを起動するためのユーザー インターフェイス要素を、ユーザーが持つ権限に従って隠すか、無効にするかどうかを決定できるようにしておくことをお勧めします。親ダイアログ ボックスが "ルート" ダイアログ ボックスの場合は、該当するメニュー項目、ダッシュボード Web パーツを "能動的に" 隠します。
ユーザー プロセスの承認設定を宣言を通じて行うには、PrincipalPermission 属性を該当するクラスまたはメソッドに対して適用します。
ユーザー プロセス コンポーネントは、基本的に、ユーザー インターフェイス コンポーネントだけが使用します。コード アクセス セキュリティを使用すると、呼び出し元を制限できます。また、ユーザー プロセス コンポーネントどうしの対話についても制限を加えることができます。特に、ポータル システムでは、プラグインとして実装されたユーザー プロセスが他のユーザー プロセスや要素から許可されていない情報を収集できないようにすることが重要です。
ビジネス コンポーネントでの承認
ビジネス コンポーネントで承認を行う場合は、次のガイドラインを参考にしてください。
-
ビジネス プロセスでの承認は、ユーザー コンテキストからできる限り切り離してください。キューや Web サービスなど、多くの通信メカニズムでは呼び出し元を偽装できないため、このような通信メカニズムを多用する場合は、特に切り離す必要があります。
-
できる限り、ユーザー アカウントの使用を避け、ロール ベースのセキュリティを使用してください。これにより、拡張性が高まると同時に、管理も簡単になります。ユーザー名で多くの別名表記がサポートされている場合の問題を回避することもできます。Enterprise Services ベースのアプリケーションではサービス コンポーネントに対してロールを定義できます。また、Enterprise Services で実行しない .NET コンポーネントに対しては、Windows のグループ機能やカスタム ロールを使用できます。
-
PrincipalPermission 属性をメソッドに適用した場合は、Identity オブジェクトで指定された認証の種類を必ずチェックしてください。.NET の PrincipalPermissionAttribute を使用すると、プリンシパルがロールに所属していることを強制できますが、認証のメカニズムは規定しないためです。
サービス エージェントとサービス インターフェイスでの承認
サービス エージェントとは、外部のサービスを呼び出すときのゲートウェイとして機能するコンポーネントです。したがって、特定のユーザーやロールからのアクセスを拒否する必要がある場合は、サービス エージェント コンポーネントに承認機能を組み込む必要があります。外部のサービスの側でも、独自の承認チェック機能を別途実装している場合もあります。
サービス インターフェイス コンポーネントに承認機能を実装するには、Web サービスの場合は IIS と ASP.NET の承認機能を使用できます。Microsoft メッセージ キューを通じてサービス インターフェイスを公開する場合は、Windows の ACL を使用できます。
データ アクセス コンポーネントでの承認
データ アクセス コンポーネントは、アプリケーションのデータに最も近いところでビジネス ロジックを公開するコンポーネントです。したがって、きめ細かく承認チェックを実行する必要があります。次のような処理が必要となる場合は、このレベルで承認を実行します。
データ アクセス コンポーネントはきめ細かなインターフェイスをその基になるシステムに対して公開するため、セキュリティは詳細レベルでだけ管理でき、特定のビジネス プロセス オペレーションで必要とされる集約が考慮されません。したがって、このレベルに承認チェックを実装する場合、上位のビジネス プロセスの実行に関する許可を設定するには、データ アクセス コンポーネントに関するアクセス許可も変更が必要になるケースがでてきます。
承認を行うには、Enterprise Services のロールを使用することもできますし、Windows 認証を使用している場合は .NET の PrincipalPermission 属性を使用することもできますし、Windows のセキュリティ コンテキストを使用しない場合は .NET のロールと属性を使用することもできます。
同じユーザー コンテキストをデータ ストアに引き渡す場合は、データベースの承認機能を使用することもできます (ストアド プロシージャへのアクセス権を許可する/拒否するなど)。ただし、この場合は、次のいずれかの条件を満たしている必要があります。
メモ 偽装されたユーザー コンテキストをデータベースにまで引き渡すと、パフォーマンスと拡張性に制限が生じます。接続プーリングはユーザーごとに処理されるためです。また、ビジネス プロセスが非同期に開始された場合、元のユーザーが自動的に偽装されることはないため、Windows のプリンシパルは使用できません。ユーザーの名前とパスワードにアクセスできる場合はこの限りではありませんが、セキュリティ面に問題があり、基本的に望ましい設計とはいえません。
データ アクセス コンポーネントは基本的に、アプリケーションの他のコンポーネントからしか呼び出されないため、呼び出し元を特定のアセンブリに制限する方法も検討してください。通常は、ユーザー インターフェイス コンポーネント、ビジネス プロセス コンポーネント、(存在する場合は) ビジネス エンティティ コンポーネントの各アセンブリに対してだけデータ アクセス コンポーネントの呼び出しを許可します。
ビジネス エンティティ コンポーネントでの承認
ビジネス エンティティ コンポーネントでは、ユーザー アカウントの場合もサービス アカウントの場合も、呼び出し元のセキュリティ コンテキストに基づいて承認規則を適用できます。たとえば、Customer (顧客) オブジェクトの個人情報へのアクセスを一部のロールのユーザーに対して拒否することもできます。このような機能を実装するには、次のことが必要となります。
-
アプリケーションを構成するすべての物理層で一貫したセキュリティ コンテキストが使われていること。ビジネス エンティティを使用する物理層はすべて、実行コンテキストで等価の Principal オブジェクトを使用している必要があります。
-
PrincipalPermission 属性に加え、ビジネス エンティティの呼び出しで PrincipalPermission.Demand を使用することにより必要なチェックを行うこと。
ビジネス エンティティ コンポーネントが能動的に承認をチェックすることもできますが、最終的な承認については、実際の処理が行われるビジネス プロセス コンポーネントとデータ アクセス コンポーネントでチェックが必要です。関連する機能についての承認処理を分散すると、承認ポリシーを同期することが必要になり、保守の負担が増えるためです。
ビジネス エンティティ コンポーネントへのアクセスは、コード アクセス セキュリティを使用してさらに制限することもできます。これにより、特定の信頼済みコードだけがビジネス エンティティを呼び出すことができるようになります。パワー ユーザーがスクリプトを作成してビジネス エンティティのオブジェクトにアクセスし、許可されていない情報を入手することを防ぐことができます。
通信のセキュリティ保護
ユーザーの認証と要求の承認を行うだけでは不十分です。アプリケーションの各層が行う通信もセキュリティ保護する必要があります。送信されているときや、キューに格納されるタイミングでデータが "覗き見" されたり、改ざんされたりすることを防ぐためです。
通信をセキュリティ保護するには、リモートのコンポーネントとサービスとの間のデータ転送をセキュリティ保護することが必要です。
通信のセキュリティ保護にあたって、認証メカニズムの使用が求められることはありませんが、通信の各エンド ポイントでなりすましが行われていないことを保証するために、一方向または双方向の認証メカニズムを組み合わせて使用することをお勧めします。
通信のセキュリティ保護にあたっては、次の選択肢があります。
-
チャネル全体のセキュリティ保護
-
SSL (Secure Sockets Layer)。HTTP チャネルの場合に推奨されるメカニズムです。標準として広く採用されており、ほとんどのファイアウォールでも SSL のポートは開かれています。サービス インターフェイスを Web に公開する場合は、SSL の使用を検討してください。
-
IPSec。通信の両端が既知のエンド ポイントで、自組織の制御下にある場合は、このメカニズムも選択肢の 1 つとして検討できます。IPSec は、データ センター内の、または同一組織のデータ センター間でのサービス、物理アプリケーション層どうしの通信でよく使われます。
-
暗号化を実装した独自のリモート処理チャネル。この手法は基本的に推奨しません。通信のセキュリティ保護のしくみを実装するには、プログラミングが複雑であることに加え、高度なセキュリティ スキルと徹底したテスティングが求められます。
-
仮想プライベート ネットワーク (VPN)。インターネット経由でポイント ツー ポイントの IP トランスポートを確立できます。特定の従業員またはパートナーがインターネット経由で内部ネットワークにアクセスする場合に最も適しています。なお、VPN を実装するには、広範囲にわたるインフラストラクチャ サポートが重要となります。
-
データのセキュリティ保護
-
メッセージの署名。メッセージが改ざんされたとしても、その記録が残るようになります。署名は、同じプロセスでの認証にも使用できます。
-
メッセージ全体の暗号化。ネットワークのパケットが侵害された場合でも、メッセージの解読は不可能です。適切なアルゴリズムによってメッセージを暗号化すると、メッセージの改ざん防止効果もあります。
-
メッセージの機密部分だけの暗号化。機密情報がメッセージの一部分にしか含まれていない場合はこの手法が効果的です。
デジタル署名の場合、基本的には、メッセージの署名部分のハッシュを計算し、署名者の秘密鍵を使用してハッシュを暗号化し、暗号化されたハッシュをヘッダーに含めます。受信者の側では、署名者の公開鍵を使用してメッセージ内の署名を解読し、メッセージの署名部分から計算して得られたハッシュと比較します。ハッシュが一致した場合、メッセージは改ざんされていないと判断できます。ハッシュが一致しない場合は、メッセージが破損していると考えられるため、該当するメッセージと呼び出し元の情報を監査の記録に残し、例外を生成して返す必要があります。
メモ メッセージをデジタル署名し、ハッシュを付けたとしても、反射攻撃を防ぐことはできません。反復攻撃とは、同じメッセージを繰り返しサーバーに送信する攻撃のことをいいます。この種の攻撃に対応するには、必要に応じて、メッセージング層に緩和ロジックを組み込んでください。たとえば、メッセージの本文にタイムスタンプを追加するか、メッセージが等羃となるようにプロセスを設計するという手法が考えられます。
たとえば、XML Web サービスの場合は、SignedXml クラスと SOAP ヘッダーを使用して XML デジタル署名を SOAP に実装することもできます。SignedXml クラスの詳細については、MSDN ライブラリの「SignedXml クラス」を参照してください。SOAP ヘッダーの詳細については、MSDN ライブラリの「SOAP ヘッダーの使用」を参照してください。
通信チャネルをセキュリティ保護する場合は、パフォーマンスの影響を考慮する必要があります。ここまでに説明した手法を採用する場合は、チャネルのセキュリティ保護を必要な場所だけにとどめてください。具体的には、特定の Web サービスの URI、特定の ASP.NET ページ、ビジネス データのうち機密部分だけをセキュリティ保護するようにします。パフォーマンスの影響の度合いは、採用するメカニズムによって異なります。また、アプリケーションが交換するデータの内容、エンド ポイントの数、採用するセキュリティ メカニズムの種類などによっても左右されます。
セキュリティ保護をサポートするチャネルの詳細については、後の「通信ポリシーの設計」を参照してください。
ユーザー インターフェイス コンポーネントでの通信のセキュリティ保護
ユーザー インターフェイス コンポーネントは、ユーザーとだけ通信します。基本的に、機密に属する情報を警告なく画面に表示することは避けてください。また、パスワードを画面に表示したり、プレーン テキストで送信したりすることは厳禁です。Web アプリケーションの場合、ログオン フォームの送信時や、個人の財務情報の表示時など、機密情報をユーザーとやり取りする場合は必ず SSL を使用してください。
ほとんどの場合、ユーザー プロセス コンポーネントとユーザー インターフェイス コンポーネントは 1 つの場所にあるため、これらの通信に使われるチャネルをセキュリティ保護する必要はありません。
サービス エージェントとサービス インターフェイスでの通信のセキュリティ保護
呼び出し先サービスとの通信チャネルに対してセキュリティ メカニズムを適用するには、サービス エージェントでこれを実装します。たとえば、メッセージの署名や SSL 接続が必要となる場合は、ロジックをサービス エージェントで実装することにより、この要件をビジネス コンポーネントとワークフローから切り離す必要があります。
XML Web サービスなど、サービス インターフェイスの場合は、通信のセキュリティ保護を強制的に適用し、これに準拠しない通信とメッセージを拒否することなどもできます。メッセージ キューおよび XML Web サービスでは、通信チャネルのセキュリティ保護を簡単に実現できます。この詳細については、後の「通信ポリシーの設計」を参照してください。
データ アクセス コンポーネントでの通信のセキュリティ保護
一般的にデータ アクセス コンポーネントは、データ アクセス ヘルパ コンポーネントを通じてデータ ストアと接続します。データ ストアとの通信の暗号化ポリシーは、その種類を問わず、データ アクセス ヘルパ コンポーネントで処理します。また、一部のデータ ストアは、複数の通信プロトコルをサポートしています。たとえば、SQL Server は、名前付きパイプ、TCP/IP、IPX/SPX などをサポートしています。組織が定める通信ポリシーにより、使用できるプロトコルが限定されるため、この設計にも影響が及びます。
サポートされる通信のセキュリティ メカニズムは、データ ソースによって異なります。データ ソースによっては、通信のセキュリティをネイティブにサポートしていないものもあります。場合によっては、プラットフォームが提供するセキュリティ メカニズムか、標準化されている SSL などのメカニズムを使用して、サービスとの通信を独自に保護する必要があります。
通信のセキュリティを適用する接続パラメータの管理は、データ アクセス ヘルパ コンポーネントで行います。たとえば、データ アクセス ヘルパ コンポーネントでは、以下をカプセル化することが考えられます。
プロファイル管理
ユーザー プロファイルとは、ユーザーに関する情報をまとめたもので、アプリケーションはこの情報に基づいて動作を切り替えることができます。ユーザー プロファイルに格納する情報には 2 種類の情報が考えられます。1 つは、ユーザー インターフェイスのオプション設定に関するもので、背景色の設定などを格納します。もう 1 つは、ユーザー自身に関する情報で、ユーザーの住所、クレジットカードの番号などを格納します。プロファイルの情報は、Principal オブジェクトを通じてコレクションとして公開できます。オフライン機能を持つアプリケーションの場合は、プロファイル情報をキャッシュに格納することも 1 つの方法です。プロファイルに機密情報が含まれる場合は、暗号化するか、ハッシュ化することによって、覗き見や改ざんを防いでください。
監査
多くのアプリケーションでは、セキュリティ対策の一環として、ユーザーや業務処理の内容を追跡管理する監査機能を実装しています。業務処理の内容を監査する場合は、セキュリティ保護されたストレージを使用する必要があります。監査とは、"セキュリティ保護されたログ記録" と言い換えることもできるからです。独自の監査機能を実装する場合は、監査記録の改ざんをできないようにするか、少なくともデジタル署名などを使用して改ざんの記録が残るようにしてください。また、ストレージのセキュリティ保護も欠かせません。たとえば、接続文字列を変更できないようにしたり、ストレージ ファイルを置き換えたりできないようにします。悪意あるコードによって偽の監査記録が書き込まれることを防ぐには、ドキュメントの署名、プラットフォームによる認証、コード アクセス セキュリティを使用できます。
監査機能のインターフェイスは、ユーティリティ関数の形でアプリケーションに公開することもできますし、監査の記録をユーザーと関連付ける必要がある場合は、アプリケーションの Principal オブジェクトのメソッドの形で公開することもできます。
ユーザー インターフェイス コンポーネントとユーザー プロセス コンポーネントでの監査
通常、ユーザー インターフェイス コンポーネントで行われた操作は監査の対象に含めません。ただし、ログオン、ログオフ、パスワードの変更、セキュリティ上の例外事象については監査の対象に含めることをお勧めします。
ユーザー プロセス コンポーネントは、ユーザーが実行した操作に対応するもので、中断や放棄があるので、これを監査の対象に含めるのは一般的ではありません。もちろん、セキュリティ関連の例外事象を監査に含めることもできます。
ビジネス プロセス コンポーネントでの監査
ビジネス プロセスが監査の主な対象となります。主だった業務処理については、いつ、だれが実行したのかを把握する必要があります。
トランザクションのコンテキストの中で監査を行い、その記録をトランザクション リソース マネージャ (SQL Server) に書き込む場合は、監査のコンポーネントによって新しいトランザクションを開始する必要があります。これにより、元のトランザクションが失敗した場合でも、監査の記録がロールバックされないようにします。
データ アクセス コンポーネントでの監査
データ アクセス コンポーネントは、データ ストアに最も近い場所に位置付けられるビジネス ロジック層です。きめ細かな承認を実装する場合と同様、きめ細かな監査を実装する場所としては、データ アクセス コンポーネントが適しています。
データ アクセス コンポーネントでは、ストアド プロシージャを呼び出して大量のデータ処理を実行することが多くなります。したがって、RDBMS の内部でも監査を行うことをお勧めします。SQL Server 内で監査を実装する方法については、MSDN ライブラリに公開されている SQL Server 2000 SDK の「SQL Server 利用状況の監査」を参照してください。
運用管理ポリシーの設計
運用管理ポリシーとは、アプリケーションの継続的な日常処理に関するもので、例外管理、監視、業務監視、メタデータ、構成、サービス ロケーションなどが含まれます。図 3.3 を参照してください。
図
3.3
運用管理ポリシーの各要素
例外管理
例外管理には、例外のキャッチとスロー、例外の設計、例外情報のフロー、例外情報の各ユーザーへの公開が含まれます。
アプリケーションは必ず、何らかの例外処理を実装して、実行時エラーをキャッチできることが必要になります。例外はできる限りキャッチして解決するようにしてください。エラー状態をどうしても解決できない場合は、ユーザーが理解できる内容のメッセージを画面に表示したうえで、デバッグ用として例外情報をログに記録するか、発行するしくみを実装します。
メモ .NET ベースのアプリケーションで例外を処理する場合の詳細については、MSDN ライブラリの「.NET における例外管理」を参照してください。
Microsoft では、ここに紹介した例外管理の実装に使用できるリファレンス アプリケーション ブロックを提供していますが、この詳細については、MSDN ライブラリの「Exception Management Application Block for .NET」(英語情報) を参照してください。
例外のキャッチとスロー
例外に関連情報を追加する場合、または例外の種類、内容に応じてビジネス フローの条件分岐を行う場合は、コードで例外をキャッチする必要があります。できる限り、例外のキャッチは層の境界で実行し、呼び出し元が処理できる例外の型にラッピングしてください。新しい例外をスローする場合は、元のキャッチした例外をスローする新しい例外オブジェクトの InnerException メンバとして保持することもできます。
例外クラスの設計
例外クラスは、ApplicationException の派生クラスとして作成します。任意のデータを例外に追加できるようにするなど、独自の機能が必要となる場合は、独自に例外クラスを作成します。Exception Management Application Block for .NET には、例外作成用の基本クラスが用意されており、追加機能が必要となる場合はこの基本クラスから派生する形で例外を作成できます。
例外には大きく分けて、業務上の例外と技術上の例外の 2 種類があります。例外をこのように分類することにより、アプリケーションのさまざまなコンポーネントで該当する種類の例外をキャッチし、発行する処理を簡単に実現できるようになります。
例外情報のフロー
例外には、アップストリームの情報フローのしくみが組み込まれています。ただし、層を越えて例外をフローさせるには、まず例外をシリアル化することが必要です。通信先がサービス インターフェイスまたはユーザー インターフェイスで、例外をそのまま引き渡すことが望ましくない場合、つまり呼び出し元に対して必要な情報を引き渡しながらも、システムや組織に対して悪用される危険性があるアプリケーションやサービスに関する業務上、技術上の機密情報を渡さないようにするには、特にこの点が重要となります。
例外のフローが発生するのは、通信が双方向の場合に限られます。メッセージ キューや一方向の通信メカニズムの場合は、メッセージでエラーが生じたことを呼び出し元に伝えるメカニズムを何らかの形で実装する必要があります。また、クライアントの側でも、メッセージがサーバーにまったく到達できなかった場合の状況を処理するしくみが必要となります。
例外情報の発行
例外が発生したら関係者に通知するしくみをアプリケーションに持たせることもできます。運用技術スタッフであれば、技術上の例外について通知される必要があり、管理職やヘルプデスクであれば、業務上の例外について通知される必要があります。通知を受ける人によって必要とされる情報は異なります。受注コードが必要となる場合もあり、例外発生元コンピュータの情報が必要となる場合もあります。
発行する情報の内容は通知先に合わせて変更し、通知先が使用するツールと通信できるチャネルを使用してください。つまり、技術上の例外の場合は WMI (Windows Management Instrumentation) イベントを発行し、業務上の例外の場合はヘルプデスクの Web サービスに通知する形になります。いずれの場合も、例外の記録はイベント ログに書き込みます。
このような機能を実装するサンプル コードについては、MSDN ライブラリの「Exception Management Application Block for .NET」(英語情報) を参照してください。
ユーザー インターフェイス コンポーネントでの例外管理
ユーザー プロセス コンポーネントでは、ビジネス プロセス コンポーネントとデータ アクセス コンポーネントで発生した例外を処理できる必要があります。また、次の判断を組み込む必要があります。
ユーザー プロセス コンポーネントでは、処理の内容によっては、例外の発生をユーザーに隠す必要があります。例外の発生を画面で通知する必要がある場合、基本的にユーザー プロセス コンポーネントでは条件分岐によってエラーの発生を何らかの形で画面要素を使用してユーザーに通知し、呼び出し元には例外を引き渡さないようにします (呼び出し元の例としては、ASP.NET ページや Windows フォームが考えられます)。
ASP.NET には、エラー状態時のユーザー インターフェイス フローについて基本的な機能がいくつか用意されており、アプリケーションの内容によってはこの機能を活用することもできます。詳細については、MSDN ライブラリの「.NET における例外管理」を参照してください。
ユーザー インターフェイス コンポーネントでは発生した例外を発行し、問題の特定に役立てるようにしてください。特にリッチ クライアント アプリケーションの場合、このことが重要です。多くの場合、例外の発行先には、中央サーバー (Web サービス経由など) が考えられますが、オフラインで機能するアプリケーションの場合はローカル ファイルやイベント ログを使用できるようになります。
ビジネス プロセス コンポーネントでの例外管理
ビジネス コンポーネントでの例外処理では、ビジネス オブジェクトが返した例外やエラーをキャッチすることに加えて、呼び出し元が処理できる例外に変換することも必要となります。また、ビジネス コンポーネントは、データ アクセス コンポーネントから引き渡された例外を処理できることが必要になります。これには、次のものがあります。
-
技術上の例外 (データベース接続の失敗など)
-
業務上の例外 (外部キー制約の違反など)
ビジネス コンポーネントでは受け取った例外をそのまま呼び出し元のコードに引き渡してください。Microsoft では、例外をそのまま引き渡すことを推奨していますが、特にクライアントの種類が 1 つしかなく、例外が抽象化されていた方が望ましい場合は、例外をラッピングすることを検討することもできます。
ビジネス コンポーネントでは、次のような状況の場合、例外を発生させる必要があります。
ビジネス コンポーネントは、たとえば次のような場合、データ アクセス コンポーネントのすべての例外を引き渡す必要があります。
-
データへのアクセスで技術的な問題が生じた場合。または、バックエンドのデータ アクセス コンポーネントでエラーが発生した場合。このような例外のほとんどは、ラッピングし直すことなくそのまま引き渡すことができます。
-
オプティミスティックなロック スキームを使用していて、読み取り後にデータが更新されているため新たに更新を実行すると既存のデータが上書きされてしまう場合 (ビジネス エンティティがユーザー インターフェイス層から呼び出される場合は、一般的にオプティミスティックなロック スキームが使われます)。
基本的に、呼び出し先の層で発生した例外をビジネス コンポーネントでとどめることは避けてください。例外を隠蔽すると、トランザクション ステートの観点からビジネス プロセスが誤った方向に導かれる可能性があり、処理が成功したとユーザーが勘違いする原因ともなりえます。
例外は、ビジネス層に発行してください。トランザクションの結果が送られるのはビジネス層であり、内部的なサービス レベルの合意が定義されるのもビジネス層であるためです。
データ アクセス コンポーネントでの例外管理
データ アクセス コンポーネントでは一般的に、次の 2 つの種類の例外を処理する必要があります。
トランザクションを実行している場合は、内容を問わず、例外が発生すると実行中のトランザクションが中断されます。データ アクセス コンポーネントで何か問題が起きた場合は、必ず Enterprise Services の現在進行中のトランザクションにその旨を明示的に通知してください。
データ コンポーネントで例外を処理するときは、基になっているデータ ソース (またはデータ アクセス API) から返されたエラーと例外をキャッチしたうえで、例外をアプリケーションの他の部分で使われている例外スキーマにマッピングする必要があります。データ アクセス コンポーネントから例外を引き渡すときは、そのクライアントが処理できる種類の例外にラッピングしてから引き渡してください。業務上の例外の場合も、技術上の例外の場合も、例外をラッピングすることにより、例外の処理構造と発行ロジックを強化でき、呼び出し元が増えた場合にも対応が簡単になります。
データ ソースの例外 (ストアド プロシージャで RAISERROR を伴って生成される SQL Server エラーを表す SqlExceptions など) を .NET ベース アプリケーションの例外スキーマにマッピングする機能は、データ アクセス コンポーネントに実装します。マッピングを実装するときは、次の点について考慮が必要です。
-
サービス固有のエラー コードまたは HResult を .NET の該当する例外の種類に変換、またはマッピングします。
-
低水準の .NET 例外を高水準の例外にラッピングします。
-
サービス API を使用して追加のエラー情報を取り出し、作成した例外の該当するフィールドに補足情報を追加します。
メモ ADO.NET など、データ アクセス API が .NET 用の API の場合、このような変換やラッピングはほとんど自動的に処理されます。したがって、データ アクセス コンポーネントで例外をキャッチしてスローし直す必要はありません。たとえば、ADO.NET では、SQL Server によりエラーが返された場合、自動的に SqlException 例外がスローされます。ただし、多くの場合では、データ アクセス API 固有の例外をラッピングし、アプリケーションが処理しやすい独自の例外に変換する必要があります。
データ アクセス コンポーネントでは必ず例外を発行してください。例外を発行する方法としては、例外の詳細情報をログ ファイルに書き込むか、警告メッセージを送信することなどが考えられます。技術上の例外と業務上の例外は異なるメカニズムによって発行することもできます。たとえば、技術的な例外の場合は WMI を通じてオペレータに警告メッセージを送信し、業務上の例外の場合はアプリケーション固有のエラー ログかデータベースに書き込むことなどが可能です。
ビジネス エンティティ コンポーネントでの例外管理
ビジネス エンティティは、ユーザー インターフェイス コンポーネントやビジネス プロセス コンポーネントから呼び出されます。したがって、例外をスローするときは、呼び出し元が処理できる形の例外を生成してスローすることが重要です。
ビジネス エンティティを SDK の形でスクリプト開発者に公開する場合は、処理しやすい形にすべての例外をラッピングし、もともとの例外は InnerException メンバとして保持しておく方法もあります。
監視
アプリケーションの稼動状態、SLA (サービス レベル契約) の遵守度、拡張性/キャパシティの管理を運用スタッフが把握できるためには、アプリケーションに何らかの計測機能を組み込んでおく必要があります。アプリケーションに計測機能を組み込む際の詳しいガイドラインについては、MSDN ライブラリの「.NET 分散型アプリケーション デザインにおける監視」を参照してください。
アプリケーションでは次のものを監視しておくことをお勧めします。
-
稼動状態の監視 各コンポーネントは正常に機能しているかどうか。一時的なロック、ハング、プロセスの終了、キューのブロックなどがないかどうか。
-
SLA
の遵守度 各ビジネス プロセスは想定どおりのパラメータの範囲内で稼動しているかどうか。各サービスは当初の期待どおりに機能しているかどうか。アプリケーションまたはサービスのパフォーマンス、応答時間が呼び出し元の期待値を下回っていないかどうか。
-
拡張性の管理 各コンポーネントを展開したコンピュータ、ファーム、ネットワークは、処理するタスクに合わせて設計、構成されているかどうか。各ソースのパフォーマンスは安定しているかどうか。
-
ビジネス
プロセスの監視 ビジネス プロセスの効率をさらに高めることはできないかどうか。重要な意思決定をより迅速に下せないか。ビジネス プロセスの効率化を妨げている組織上の障害はどこか。
監視が必要な項目の種類はさまざまですが、アプリケーションやサービスをしかるべく監視することによって、これらの質問の答えを得ることができます。すべての項目を常時監視する必要はありません。ビジネス プロセス上の課題については、アプリケーションのバージョンアップを計画するときに監視することもできます。
ビジネスの監視
ビジネスの監視は、業務上の意思決定者に各種の事後報告資料を提出するためにあります。これには、ビジネス プロセスの稼動状況、ビジネス レベルでの SLA の遵守度、組織の受容能力管理などが含まれます。ネットワーク エラーが存在するなどの情報とは異なり、ビジネス プロセスの監視からは、ビジネスの構造やプロセスの効率性などの情報を得ることができます。たとえば、特定のパートナーが配送出荷を行うと必ずビジネス プロセスが数日にわたって遅滞することなどの情報を得ることができます。
ビジネス プロセスの監視は、ビジネス インテリジェンスの一部です。しかし、OLAP 分析やデータ マイニングを置き換えるものではありません。OLAP 分析やデータ マイニングは、アプリケーションまたはサービスのデータ ストアから ETL (Extract、Transform、Load : 抽出、変換、読み込み) の一連のプロセスを経て取り出したデータを利用し、過去のデータの傾向から事前措置としての意思決定を下せるようにすることを目的としています。大きな違いとしては、業務指標は変化しやすいこと、そしてアプリケーションのデータに反映されるとは限らないことがあります。
ユーザー プロセス コンポーネントでの監視
ユーザー プロセス コンポーネントからは、興味深い業務統計を得ることができます。この結果は、アプリケーションの UI デザインを改善し、ユーザーとの対話を効率化するための参考になります。ユーザー プロセス コンポーネントから得ることができる指標の一例を次に示します。
-
ユーザー プロセスの平均存続期間。
-
ユーザー プロセスが特定箇所で中断していないかどうか。これは、ユーザー インターフェイスに問題がないかどうかの指標になります。業務情報を十分に提供しているかどうか、わかりやすい設計になっているかどうかを確認しましょう。
-
開始されたまま完了されないユーザー プロセスがないかどうか。ある場合は、どの段階でキャンセルされているか。この情報を参考にすると、ユーザー インターフェイスの設計を見直して、ユーザーがプロセスを開始する必要があるかどうかを早い段階で正しく判断できるようになります。
ビジネス プロセス コンポーネントとワークフローでの監視
ビジネス プロセス コンポーネントとワークフローは、トランザクションの結果が最終的に渡される場所であると同時に、業務処理、サービス、データ ストアの問題の伝達経路となる場所です。そのため、稼動状態の監視は非常に重要です。MSDN ライブラリの「.NET 分散型アプリケーション デザインにおける監視」の説明に従い、各クラスに計測ロジックを実装してください。
ビジネス レベルの監視は、原則としてすべてビジネス層で行います。ビジネス層の実装に Enterprise Services (COM+) を使用している場合は、Xtremesoft 社の AppMetrics for COM+
(英語情報) を利用できます。BizTalk のワークフローの監視には、BizTalk Document Tracking を利用できます。また、Xtremesoft 社は、AppMetrics for BizTalk Server も提供しています。
BizTalk Server でのドキュメントの追跡管理については、MSDN ライブラリの「BizTalk ドキュメント トラッキングの使用」を参照してください。
データ アクセス コンポーネントでの監視
データ アクセス コンポーネントは、トランザクションに加わり、データ サービスとの接続を処理するデータ アクセス API コンポーネントと対話します。データ アクセス コンポーネントも、重要な監視対象に含めることができます。ここでは、長時間にわたるデータ処理の時間、オブジェクトの存続期間、処理のスループットと待機時間、メモリの利用状況、その他の稼動状況に関する技術的な指標を追跡管理します。
トランザクションの中断は、アプリケーション全体に大きな影響を及ぼします。データ アクセス コンポーネントを監視し、例外の発行ポリシーを最適化すると、失敗の回数が多いコンポーネントをビジネス ロジックなどから切り離しやすくなります。
また、データベースに接続するところでは、接続の利用状況、接続プーリングの統計情報、接続セキュリティの統計情報も監視する必要があります。
外部のデータやデータ ソースの利用が SLA に含まれている場合は、外部データの応答時間も監視の対象に含めます。
監視機能をコンポーネントに組み込む際のガイドラインについては、MSDN ライブラリの「">.NET 分散型アプリケーション デザインにおける監視」を参照してください。
ビジネス層の実装に Enterprise Services を使用している場合は、Xtremesoft 社の AppMetrics for COM+
(英語情報) を使用できます。または、「.NET 分散型アプリケーション デザインにおける監視」に解説されている計測ロジック付きクラスを使用できます。
構成
アプリケーションが正常に機能するためには、構成情報が必要です。ポリシー (セキュリティ ポリシー、運用管理ポリシー、通信ポリシー) の適用に影響を及ぼす設定情報のことを構成データとして考えます。
構成データは、ユーザー単位、マシン単位、アプリケーション単位で適用でき、.NET 構成ファイルに格納します。構成データは任意のスキーマで格納でき、ConfigurationSettings クラスを使用するとアプリケーションから簡単にアクセスできます。
構成データのセキュリティも、重要です。SQL の接続文字列、特に SQL の資格情報を XML 構成ファイルにクリア テキストのまま格納することは避けてください。機密情報は特定のオペレータのみがアクセスできるようにしておく必要があります。セキュリティを高めるには、デジタル署名を使用して、構成データの改ざんを防ぐことも必要です。
構成データはさまざまな場所に格納できます。場所ごとにメリットとデメリットがあります。
-
アプリケーション
XML
構成ファイル 構成データを XML ファイルに格納した場合、アプリケーション クライアントはオフライン環境でも動作でき、実装も簡単です。ただし、リッチ クライアント アプリケーションの場合、すべてのクライアントで構成情報を統一する必要があるため、変更管理のコストが増大するという側面があります。サーバー環境の場合は、構成データに変更があったときでも、Application Center サーバーや Microsoft Active Directory のディレクトリ サーバーを使用するか、バッチ ファイルを使用すると、変更内容を各クライアントに簡単に渡すことができます。構成データを読み込み直すには、AppDomain の再起動が必要となります。なお、ASP.NET の場合は、構成ファイルに変更が検出されると AppDomain が自動的に再起動されます。アプリケーション構成ファイルはプレーン テキストに格納することになるので、セキュリティ リスクの観点からこの方法を採用できない場合もあります。原則として、ユーザー名とパスワードを含む接続文字列をアプリケーション構成ファイルに格納することは絶対に避けてください。
-
SQL Server
またはアプリケーションのデータ
ストア アプリケーションが管理する構成データ、特にアプリケーションのメタデータの格納場所として多く使われます。メタデータを SQL Server に格納する場合は、できる限り、業務データとは異なるデータベースに格納してください。データベースへのアクセスが多いと、パフォーマンスの低下につながるため、キャッシュの利用を検討してください。
-
Active Directory ユーザーが組織内に限られる場合は、アプリケーションのメタデータを Active Directory に格納することも選択肢となります。Active Directory に格納すると、ドメイン内のすべてのクライアントがメタデータにアクセスできます。また、Active Directory 内の情報は Windows の ACL を通じてセキュリティ保護できます。これにより、特別に許可されたユーザーとサービス アカウント以外はアクセスできないようになります。
-
コンストラクタ文字列 Enterprise Services ベースのコンポーネントを使用している場合は、構成データをコンポーネントのコンストラクタ文字列に含めることもできます。
-
その他の場所 Windows のレジストリ、LSA (Local Security Authority) ストアなどが考えられます。独自の実装を利用することもできます。これは特別な場合に限り使用してください。この場合は、コンピュータに対する特権をアプリケーションに与えたり、展開のしくみを用意したりする必要が生じます。
-
サードパーティの構成管理ソリューションの中には、バージョン管理と展開管理の機能を提供するものもあります。
構成データおよびメタデータへのアクセスは、多くの場合、特に構成データがリモート システムに格納されている場合は、パフォーマンスの低下につながります。パフォーマンスの低下を防ぐには、アプリケーションが管理する構成データとメタデータをメモリ キャッシュに格納する方法が考えられます。ただし、機密に属する情報を本来アクセスすべきでないアプリケーション コードに開示することによって、セキュリティ ホールを作り出すようなことがないよう注意してください。構成データをキャッシュする場合は、キャッシュ データをフラッシュして、リフレッシュする間隔を指定しておくことをお勧めします。なお、1 時間ごとに更新するというような設定ではなく、"毎時 00 分に更新する" など、時刻を絶対指定するようにしてください。これにより、アプリケーションが読み込んでいる構成データを常に正確に把握しておくことができます。
プレゼンテーション層での構成
ユーザー プロセス コンポーネントの多くでは、次のような構成情報が必要となります。
サービス エージェントでの構成
サービス エージェントでは、Web サービス、メッセージ キューを使用する外部サービスへの接続に使用する情報を構成情報として保持する必要があります。構成情報のスキーマと実際のデータの内容は、アクセス先のサービスによって異なります。
データ アクセス コンポーネントでの構成
データ アクセス コンポーネントで必要となるものは、以下のとおりです。
-
論理的なデータ ソース名を物理的なパラメータにマッピングするしくみが必要です。たとえば、"営業" データベースを実際の接続文字列にマッピングできることが必要になります。
-
データ アクセス コンポーネントが動的なデータ ルーティングを行う場合は、ルーティング パラメータ (顧客の地域など)、アルゴリズム (ハッシュなど)、ルーティングの宛先 (データベースへの接続文字列など) が構成データに含まれている必要があります。動的なデータ ルーティングのロジックは、多くの場合、独立したユーティリティ コンポーネントにラッピングします。
メタデータ
実行環境の変化に柔軟に対応するには、アプリケーション自体に関する情報を何らかの形で管理しておく必要があります。メタデータを効果的に使うようアプリケーションを設計すると、保守が簡素になり、環境が変化したときでもコストのかかる開発や展開のやり直しの必要なくアプリケーションを変化に対応させることができます。
メタデータを利用できるタイミングには、主に、次の 2 つがあります。
-
デザイン時 たとえば、データベースに関する情報から、コード、ストアド プロシージャ、.NET のクラスを生成することが考えられます。また、使用頻度の高いパターンがある場合は、このような情報からユーザー インターフェイスのコンポーネントを生成することもできます。開発時にメタデータを活用すると、時間を節約でき、チーム内のコミュニケーションの必要を減らし、各自の専門スキルだけに集中でき、設計、名前付け、実装の一貫性を保つことができます。この結果、コンポーネントの動作は予想がしやすくなり、エラーの可能性が少なくなるため、開発者の生産性が向上します。ただし、このアプローチを採用するには、特殊な知識のほか、開発の初期段階では、テンプレートを作成したり、メタデータとテンプレートを結合するコードを記述したりすることが必要になります。
-
実行時 変更の頻度が高いところでは、効果的にメタデータを使うことによって、アプリケーションの保守が簡単になります。たとえば、UI リストやグリッドの見出し行の文字列をメタデータから取り出すようにすると、アプリケーションにハードコーディングせずに済みます。また、コンポーネント間のリレーションシップを確立するときや、入力規則など特定のパターンを処理するときなども、メタデータを活用できます。ただし、実行時にメタデータを使用すると、パフォーマンスの低下につながることがあります。したがって、開発の初期段階でアプリケーションのデザインをテストし、パフォーマンスを評価してください。コンポーネントを設計するときは、コンポーネント自体のメタデータを公開するよう設計することもできますが、これはアプリケーションで特別に必要な場合を除いては避けてください。メタデータがセキュリティ ホールとなることがあるためです。
実行時にメタデータを使うことによって生じるパフォーマンス上のマイナス面は、"アプリケーションの実行中に"、.NET リフレクション クラスを使用してコードを動的に生成してコンパイルするという高度なテクニックを使うことにより回避できます。ただし、この設計手法は複雑なため、ごく一部の例外を除き推奨できません。高度なスキルが求められるだけでなく、実行時のコード コンパイルとメタデータのストレージの問題から、セキュリティ ホールの可能性が生まれることがあります。実行時のカスタマイズを実装するには、ほとんどの場合、.NET スクリプティングを使用する方が簡単です。.NET スクリプティングの詳細については、MSDN ライブラリの「Script Happens .NET」(英語情報) を参照してください。
メタデータは、構成データと同様、さまざまな場所に格納できます。メタデータを一元管理するには、SQL Server データベースか Active Directory を使用します。アセンブリと一緒にメタデータも分散展開する場合は、XML ファイルの形で実装するか、独自の .NET 属性を使用するという方法もあります。
メタデータを使用したソフトウェア デザインは、メタプログラミングと呼ばれることもあり、内包的プログラミングとも関係があります。この概念の基礎については、『Generative Programming: Methods, Tools and Applications』(Krzysztof Czarnecki、Ulrich Eisenecker 共著、ISBN : 0201309777) を参照してください。
以下では、メタデータの活用法の一例を紹介していきます。
ユーザー インターフェイス コンポーネントでのメタデータ
ユーザー インターフェイスでは、アプリケーションのビジネス データに一切関係しない項目に対してメタデータを使用するケースが一般的です。具体的には、列見出し、ユーザー アシスタンス テキスト、エラー メッセージ、メニュー階層などで使用します。
アプリケーションに何らかのカスタマイズ機能を組み込む場合は、基本的に、カスタマイズ オプションの管理の簡素化を目的としてメタデータを使用します。複雑なカスタマイズが必要となる場合は、.NET スクリプティングの方が適しています。
ユーザー プロセス コンポーネントでのメタデータ
ユーザー プロセスの一貫性を重視してモデリングする場合は、次のような場面でメタデータを使うと、保守性に優れたデザインを導き出すことができます。
-
どのユーザー プロセスが存在しているか。また、どのメニュー項目がユーザー プロセスを引き起こすか。
-
UI プロセスにおいてどのような内部業務状態が必要か。既定値をどうするか。
-
ユーザー プロセスの動作の表現をどうするか (顧客が "購入の確定" をクリックしたときにどの UI コンポーネントを表示するか)。
ビジネス プロセス コンポーネントでのメタデータ
ビジネス プロセス コンポーネントでも、メタデータを使うことにより、ルール、パターンをシンプルにモデリングできるようになります。パイプライン パターンは、その一例です。パイプライン パターンは、どのクラス、どのメソッドをどの順番で呼び出すかをメタデータで規定するエンジンとして実装できます。この具体例は、Microsoft Commerce Server 2002 の購買パイプラインに見ることができます。また、メタデータを使用すると、特定のビジネス処理の箇所でコンポーネントの ID 補完メソッドを簡単に呼び出すことができるようになります。
データ アクセス コンポーネントでのメタデータ
データ アクセス コンポーネントが CRUD (Create、Read、Update、Delete) 機能のインターフェイスを公開している場合は、返されるデータと使われるメタデータのスキーマを公開することをお勧めします。同様に、特殊なクエリやアクションについては、複雑な入力パラメータ、出力パラメータの XSD スキーマも公開してください。
データ アクセス コンポーネントでデータの変換やマッピングを実行する場合は、手続き型のコードの代わりに、メタデータを使用する手法もあります。具体的には、XSL ドキュメントを使用して XML のスキーマを変換する、ルール ベースのアプローチでマッピングを実行する、SQLXML 注釈付きスキーマを使用して XML ドキュメントをデータベース内のデータにマッピングする、などが考えられます。特にマッピングを頻繁に変更する場合は、メタデータの使用をお勧めします。
ビジネス エンティティ コンポーネントでのメタデータ
ビジネス エンティティのメタデータはできる限りコンシューマに公開してください。特に、ユーザー インターフェイス コンポーネントでは、メタデータが公開されていると、次の処理を効率よく実行できるようになります。
-
グリッドの列見出しを設定します。
-
属性の説明情報をツールヒントとして表示したり、補足テキストとしてユーザー インターフェイスに表示します。
-
アプリケーションの論理エンティティ間のリレーションシップを使用してユーザー インターフェイスでこれを公開し、そのナビゲーション機能を提供します。
-
ビジネス エンティティのデータの値を検査する。これにより、ユーザー インターフェイスは能動的に値の検査を行うことができます。値の検査の例としては、顧客ごとに登録できる住所の最大数、データの書式などがあります。
メタデータの公開には、XSD を使用することも、独自のスキーマによる XML ドキュメントを使用することもできます。
入力規則を頻繁に変更が必要になる場合は、メタデータとして管理することをお勧めします。入力規則をメタデータとしてまとめておけば、変更が必要なときでも、ビジネス エンティティ コンポーネントを実装し直したり、展開し直したりする必要がありません。ビジネス エンティティがクライアントのデスクトップから呼び出される場合には変更管理が高くつくため、メタデータの使用を強く推奨します。エンティティの入力規則は XSD スキーマに記述して、アプリケーションと一緒に展開できます。
サービスのロケーション
リモート サービスを呼び出すときは、要求を処理できる .NET オブジェクトと外部サービスの場所を特定し、そこに到達する方法を指定する必要があります。他の組織やサードパーティがホストする Web サービスを使用する場合には、特にこのような情報が必須です。
ローカル アセンブリの場所の指定
.NET には、どのアセンブリにリンクするのかを実行時に指定できる機能が豊富に用意されています。.NET でオブジェクトの作成時にローカル アセンブリを特定する方法の技術的詳細については、MSDN ライブラリの「ランタイムがアセンブリを検索する方法」を参照してください。
.NET リモート処理のクラスの場所の指定
.NET リモート処理を利用すると、別のアプリケーション ドメイン、別のプロセス、または別のコンピュータにあるオブジェクトを呼び出すことができます。リモート処理で使うオブジェクトを公開するには、またはリモート呼び出しするオブジェクトを特定するには、構成情報を指定するか、必要なコードをアプリケーション内に記述します。また、リモート通信に使うチャネルの情報もアプリケーションで指定する必要があります。
.NET リモート処理の構成情報を使用して型を公開し、型を検索し、チャネルを登録する方法の詳細については、MSDN ライブラリの「構成ファイルを使用したリモート オブジェクトの登録」を参照してください。
非同期メッセージ処理でのメッセージ キューのキューの場所の指定
メッセージ キューでメッセージを送信するには、送信先のキューについての情報が必要です。メッセージ キューのキューの参照方法は、メッセージ キューの構成とメッセージをインターネット経由で送信するかどうかによって異なります。
メッセージ キューがドメイン構成でインストールされている場合は、名前、ID などの属性を使用してキューを特定できます。Windows 2000 の MSMQ 2.0 でこの機能を使用するには、キューのクライアントとサーバーの両方が同じドメイン コントローラを参照している必要があります。Active Directory 内のキューの登録情報は、ドメイン コントローラで管理されます。ドメイン構成の場合は、ラベルまたは FormatName を使用してキューの場所を指定できます。
メッセージ キューがワークグループ構成で送信元にインストールされている場合は、キューの絶対パスを指定する必要があります。メッセージ キューの使用に関する詳細については、MSDN ライブラリの以下のドキュメントを参照してください。
インターネット上のまたは組織内の Web サービスの場所の指定
XML Web サービスの URI は、アプリケーション構成ファイルに記述しておき、実行時に動的に取り出すことができます。この手法であれば、アプリケーションの保守も簡単です。Web サービスの場所情報を構成ファイルに記述する方法の詳細については、MSDN ライブラリの「Web 参照」を参照してください。
業界では、UDDI (Universal Description, Discovery, and Integration) という規格が普及しつつあります。UDDI を使用すると、サービスや企業が他のサービスを検索したり、サービスとそのインターフェイスを他の呼び出し元に対して公開したりできます。UDDI は、SOAP、WSDL、DNS などの標準規格をベースにしているため、特定のプラットフォームに依存することはありません。ワールドワイドの UDDI レジストリを使うことにより、開発したサービスを外部のパートナーやサービスに対して公開することもできます。または、UDDI 仕様を独自に実装して、内部サービスの場所指定と統合のしくみの基盤とすることもできます。
Microsoft Windows Server 2003 では、UDDI サービスがネイティブにサポートされています。この詳細については、Windows Server 2003 Web サイトを参照してください。Microsoft Server 2003 を使用できない場合は、Microsoft UDDI SDK (英語情報) を使用すると UDDI をローカル コンピュータにインストールできます。
UDDI の詳細については、UDDI Web サイト
(英語情報)、および MSDN ライブラリの以下の資料を参照してください。
通信ポリシーの設計
通信ポリシーでは、アプリケーション内の各コンポーネントがお互いにどのように通信するのかを規定します。通信ポリシーには、同期性、フォーマット、プロトコルを含めます。図 3.4 を参照してください。
図
3.4
通信ポリシーの構成要素
適切な通信モデルの選択
アプリケーションの各コンポーネントが通信に使う手法は、慎重に選ぶ必要があります。基本的には、メッセージを使用するか、DCOM や .NET リモート処理など、密結合型の接続手法を使用します。密結合の接続手法の方が、設計、実装が簡単ですが、拡張性、可用性、管理性の点で限界があることも事実です。
アプリケーション内通信とアプリケーション間通信の分離
アプリケーション間の通信 (つまり、外部サービスとの通信) は、SOAP ベースの XML Web サービスか、Microsoft メッセージ キューなど、メッセージ ベースのモデルを使用して実装することをお勧めします。ただし、アプリケーション内の各コンポーネントの通信では、高いパフォーマンスが求められるだけでなく、トランザクションやセキュリティ コンテキストのフローなど、特別な機能も求められます。このような要件は、DCOM など、密結合型の通信モデルを使用すると簡単に満たすことができます。トランザクションや ID のフローが必要ない場合は、アプリケーション内の各コンポーネント間の通信にも XML Web サービスを利用できます。アプリケーションの通信メカニズムには、できる限りメッセージ ベースの手法を採用することをお勧めします。これには、ユーザー インターフェイス層とビジネス プロセス間の通信、サービス インターフェイスとビジネス層間の通信も含まれます。
メモ XML Web サービスは現時点では、トランザクションおよび ID フローのしくみが標準化されていません。これらの点については、GXA (Global XML Web Services Architecture) でトランザクションとセキュリティに関する仕様を定めることにより対応される予定です。GXA の詳細については、「Web サービスに関する仕様について」を参照してください。
アプリケーション間の通信とアプリケーション内の通信では、要件事項と制限事項が異なり、どのテクノロジを採用するかの判断は、これらの要件事項、制限事項によって左右されます。基本的には、コンポーネントを密に結合し、1 つの単位として構築、展開、管理する方が、保守の問題を簡単に解決できます。しかし、場合によっては、アプリケーションの各コンポーネントをサービスとして展開し、疎結合を一貫して使うことも 1 つの方法です。疎結合は、関連性のないアプリケーション コンポーネント間の通信によく使われます。図 3.5 は、このモデルを図に表したものです。
図
3.5
メッセージ
バスを使用してプレゼンテーション層とビジネス層間の通信を実装した場合
図 3.5 では、アプリケーションをサービス (1) として設計し、アクセスにはメッセージ バス (2) を使用します。プレゼンテーション層 (3) では、他の呼び出し側サービス (4) と同じ通信メカニズムを使います。他のサービス (6) を直接呼び出すときにもこのメカニズムを使用できます。サービス エージェント (5) が他のサービスを呼び出すときにも、同じメッセージ バスを使用します (6)。データ コンポーネントとの通信には、ほとんどの場合、メッセージ バス以外の通信メカニズム (7) が使われます。ただし、データ対データまたはプロセス対データのシナリオでデータを公開する必要がある場合は、この限りではありません。この場合は、データ ソースへのアクセスにもメッセージ バスを使用することになります。
すべてのコンポーネントとサービスで同一の通信メカニズムを採用すると、システム設計のモジュール化が簡単になり、他のサービスは統合する機能をきめ細かく選択できます。また、チーム間の独立性、各コンポーネントで使うプラットフォーム間の独立性も高めることができます。
システムの長期的な戦略として、各コンポーネントをサービスとして展開することを検討している場合もあります。しかし、これには、次のような設計上の課題が発生することがあります。
-
ユーザー インターフェイスが提供するセキュリティ情報などのコンテキストにビジネス層が依存している場合、アプリケーションからこのようなビジネス ロジックを呼び出すことはできません。
-
メッセージ バスまたは通信メカニズムは、アプリケーション内通信で求められる要件事項をすべてサポートすることが必要です。これには、トランザクション フロー、大量のデータの効率的な転送、高いスループット、短い待ち時間、多様な例外情報の転送などが含まれます。これらのすべての領域において標準化の動きは進んでいますが、現時点ではまだ、複雑な開発モデルが強いられます。
-
ユーザー インターフェイス層とビジネス層の間の通信について、サービス間で求められるレベルの柔軟性、可用性を設計することは困難です。ユーザー インターフェイス層とビジネス層の間は、サービス間で使われる標準規格を基にして通信を設計するには最適な場所です。データ層とビジネス層の間の通信には、高い処理効率が求められるため、非標準的な通信メカニズムの採用が避けられないケースが多くなります。
従来的なアプリケーション デザインを踏襲し、アーキテクチャ全体の観点からサービスの統合を重要視しない場合は、統合の場面でだけ Web サービスなどの標準ベースのメッセージ メカニズムを使用し、アプリケーション内の通信には DCOM や .NET リモート処理を使用するという判断もあります (図 3.6)。
図
3.6
特に統合が必要なところでだけメッセージ
バスを使用する場合
図 3.6 の場合、プレゼンテーション層、ビジネス層、データ層は、処理効率は高いが非標準的な通信メカニズムを通じて相互に通信します。標準化されているメッセージ ベースの通信は、特に統合が必要なところ (サービス インターフェイスとサービス エージェント) でだけ導入します。サービス インターフェイスは、外部の呼び出し元 (3、4) からの呼び出しを受け付け、サービス エージェントは、他のサービス (5、6) への呼び出しを実行します。
メッセージ ベースの通信メカニズムは、特にストア アンド フォーワード型のトランスポートに非同期に実装される場合、統合用通信の最適な選択肢といえます。しかし、デメリットがないわけではありません。正しく実装するには、数多くの設計上の課題を解決することが必要になります。
非同期型のメッセージ ベースの通信のメリット
非同期型のメッセージ ベースの通信メカニズムには、次のような利点があります。
-
拡張性と可用性 (堅牢性と柔軟性の両方の観点から) アプリケーションとサービスの拡張性と可用性の強化に貢献します。メッセージ ベースの通信では、ハードウェア リソースを有効に活用でき、ソフトウェアやインフラストラクチャの障害からアプリケーションを切り離すことができます。
-
場所の透過性 メッセージ ベースの通信では、接続が存在しなくてもメッセージを常に送信できるため、リモート側機能の真の透過性を実現できます。
-
ビジネス
モデルの踏襲 現実世界のビジネス プロセスのほとんどは、組織間、ユーザー間の情報交換を考えた場合、非同期で処理されています。メッセージ ベースの通信を使用すると、業務上の要件とアプリケーションの動作を簡潔にマッピングできます。
-
SLA
の分離 SLA の定義と遵守は、メッセージ交換をベースにした方が簡単です。また、メッセージ ベースの通信を使用すると、内部のビジネス プロセスまたは外部のサービスに存在するボトルネックを、ユーザーに対して保証するパフォーマンス SLA から切り離すことができるようになります。
-
トランスポートからの独立 メッセージ ベースの通信メカニズムを正しく導入しておけば、将来新しいメッセージング テクノロジが登場した場合にも、新しいテクノロジを簡単にアプリケーションやサービスに組み込むことができます。
メッセージ ベースの通信のデメリット
メッセージ ベースの通信に難点がないわけではありません。以下に、設計上の課題事項を示しますが、常に前に述べた利点を念頭に置いておいてください。メッセージ ベースの通信メカニズムを設計するには、一定の努力を要しますが、長期的にはそのコストを簡単に回収できるからです。メッセージ ベースの通信のデメリットは以下のとおりです。
-
結果の不確定性 密結合のシステムでは、要求が成功したか失敗したかを最後に必ず知ることができます。メッセージ ベースの通信の場合は、応答メッセージが返されていない状態についても管理が必要です。つまり、通常のビジネス ロジックに加えて、"対話中の状態" も管理する必要があります。応答が到着しなかった場合に備えて送信メッセージを記録しておくことも必要です。
-
メッセージの対応付け 送信したメッセージと受信したメッセージを自動的に対応付けるしくみは存在しません。したがって、どのメッセージがどのビジネス プロセスまたはどの対話のどのインスタンスに関連したものかを識別するしくみが必要となります。この対応付けのメカニズムは、メッセージ トランスポートに実装することもできますし、ビジネス データに実装することもできます。メッセージ トランスポートに実装する場合は、メッセージ キューのメッセージの対応付け ID を設定します。対応付けのメカニズムをビジネス データに実装すると、メッセージ トランスポートの変更が必要になった場合も簡単に切り替えることができ、ビジネス プロセスの等羃性を実現できます。
-
メッセージの遅延 メッセージは期待どおりのタイミングで到着するとは限りません。ビジネス ロジックを実装するときは、メッセージが到着しなかった場合にも対応しておく必要があります。また、メッセージを受信するロジックでは、受信したメッセージがそのタイミングでも有効かどうかを確認する必要があります。注文情報を受け取る場所では、"期限" を設け、期限が過ぎたら注文を処理しないというしくみが考えられます。ここでは例として、呼び出し元が注文情報を送信してから、そのメッセージが受信されるまでの間に、商品の価格が変更されてしまった場合を考えてみましょう。この場合は、変更後の価格で注文を処理するか、変更前の価格で処理するか、処理をキャンセルするかを指定することが必要です。場合によっては、商品の価格など、重要なデータについて "リファレンス データ" をメッセージに含めるという方法もあります。これにより、ビジネス ロジックは変更前後の価格を比較したうえで、メッセージに関してきめ細かい判断を処理できるようになります。
-
トランザクション
フロー メッセージ ベースの通信では、トランザクション モデルが異なります。トランザクション対応のトランスポート (トランザクション対応のメッセージ キューなど) を使用している場合、トランザクションのコミットにより、"送信" 処理が行われたことを確認できます。ただし、トランザクション メッセージの送信とその応答の受信を 1 つのアトミック トランザクションのコンテキストにまとめることはできません。処理に時間がかかるトランザクションの場合は、複数回にわたるメッセージ交換の対話を管理し、必要な補正処理を公開することが必要になります。
-
メッセージの繰り返し メッセージが複数回到着した場合に備えたロジックを設計する必要があります。これに対応するには、同じメッセージを複数回受信した場合、プロセスとロジックが等羃になるよう設計します。たとえば、顧客の口座から出金して小売店の口座に入金する支払処理サービスの場合、支払要求のメッセージを複数回受信したとしても、1 つの支払を複数回処理してしまうことは避ける必要があります。この問題を解決するには、支払要求にトランザクション ID を含め、トランザクション ID が同じ要求は 2 回目以降すべて無視する方法が考えられます。また、データベースを更新する処理で更新前のデータと更新後のデータを指定することにより、等羃のロジックを実装することもできます。ビジネス ロジックにこのようなしくみがあれば、注文の出荷属性を "未出荷" から "出荷済み" に変更する要求メッセージを 2 回受信したとしても、問題が起こることはありません。
-
メッセージの順番 複数のメッセージの到着を待機する場合、各メッセージが期待どおりの順番で受信されるとは限りません。この場合は、対話状態を管理するか、ビジネス ロジックでこの問題を解決します。応答がない限り対話が進行しないようにすると、メッセージの順番をビジネス ロジックで強制的に適用することもできます。たとえば、注文情報の更新に関するメッセージには、発行元に対して提供済みの ID 番号の添付を要求することも 1 つの方法です。この設計手法は、メッセージ ベースの通信の利点の一部と矛盾するものであるため、必要な場合に限り使用してください。
メッセージ ベースの通信のシナリオ
次の状況に当てはまるときは、アプリケーションまたはサービスのインターフェイスを (SOAP など) メッセージ ベースにして、(メッセージ キューなど) 非同期型のストア アンド フォーワード メカニズムを使用します。
-
中長期的な投資となるビジネス システムを開発している場合。長期にわたってパートナーに公開し、パートナーが利用するサービスを構築する場合。
-
高い可用性が求められる大規模システムを開発している場合。
-
開発しているサービスを他の接続先サービスと他の公開先サービスから切り離したい場合。
-
ワイヤレス ネットワークを使用する場合や、オフライン対応のアプリケーションであるなど、エンド ポイント間の通信が断続的に切断されることが想定される場合。
同期問題
メッセージ ベースの通信は、基本的に、非同期モデルであると考えます。メッセージ キューを使用して 2 つのアプリケーションが通信する場合、メッセージが使われることからもこのことは明らかです。ただし、メッセージ ベースの通信を同期プログラミング モデルでカプセル化できます。この場合は、Microsoft Visual Studio® .NET で生成できる Web サービス プロキシなどを使用し、クライアントは応答メッセージを待機することになります。アプリケーション開発者はメッセージ ベースの通信の利点を享受しながらも、非同期モデルで必要となる複雑なプログラミングから解放されます。
詳細については、MSDN ライブラリの「Architectural Options for Asynchronous Workflow」(英語情報) を参照してください。
非同期通信の各種テクノロジ
非同期通信には、さまざまな手法を利用できます。具体的には、メッセージ キュー、XML Web サービスなどのメッセージ ベースの手法のほか、.NET リモート処理、DCOM などの接続型の手法も利用できます。この中で、柔軟性と機能の豊富さでは、キュー ベースのテクノロジが最も優れています。メッセージ キューは、ストア アンド フォーワード方式のメッセージ トランスポートをアプリケーションに対して提供します。メッセージ キューの利点は拡張性と可用性だけではありません。数多くの開発オプションがサポートされるため、アプリケーションの開発と展開のさまざまなシナリオに柔軟に対応できます。
メッセージ キューには、次のオプションと機能があります。
次バージョンのメッセージ キューの詳細については、Windows XP の Message Queuing 3.0 の新機能 を参照してください。
メッセージ キューを使用する場合は、エンド ポイントのテクノロジとメッセージのフォーマットを決める必要があります。使用できるエンド ポイントとフォーマットは以下のとおりです。
-
送受信先のエンド ポイント
System.Messaging 名前空間のオブジェクトを使うコードを開発することも、メッセージ キューのトリガ サービスを使用してメッセージを待機することもできます。両方のエンド ポイントが管理下にあり、メッセージ フォーマットについて要件が存在しない場合は、Enterprise Services Queued Components を使用できます。これは、メッセージ キュー関連の開発作業を完全にカプセル化する役割を担うものです。エンド ポイントには、COM ベースのアプリケーション、BizTalk Server のポート、MQSeries などのメッセージング テクノロジへのブリッジなどを使用できます。
-
フォーマット
SOAP、バイナリ、Microsoft ActiveX® の各フォーマットを利用できます。SOAP は、相互運用性が重視される場合に使用し、バイナリは、メッセージ サイズの効率が重視される場合に使用し、ActiveX は、COM ベースのセンダとリスナとの相互運用が重視される場合に使用します。MSMQ は COM ベースのため、MSMQ トリガでは ActiveX フォーマットを使用する必要があります。Queued Components は、非透過性の DCE RPC フォーマットでメッセージを送信します。ただし、開発者はこのことを特に意識する必要はありません。
Enterprise Services Queued Components
Enterprise Services Queued Components は、以下の状況で利用できます。
-
メッセージの送信側と受信側の両方を制御できる場合。
-
受信側のコンポーネントがサービス コンポーネントの場合。
-
メッセージのフォーマットが重要でない場合 (非透過的な RPC NDR バイナリ フォーマットが使用されます)。
Queued Components には、以下の利点があります。
-
Enterprise Services のロール ベースの承認機能を利用できます。メッセージを送信側で署名するコードを記述する必要はありません。
-
メッセージ キューには、再試行のメカニズムが組み込まれており、メッセージの実行保証を得ることができます。
-
エラーの通知を処理する例外クラスを使用でき、これを受けて適切な例外処理を実装できます。
-
メッセージの送信側は、COM でも .NET でもかまいません。
-
Enterprise Services のモデルでは、トランザクションを透過的に使用できます。
メッセージ キューのトリガ
メッセージ キューのトリガは、リスナ サービスを提供します。メッセージ キューのトリガは、以下の状況で利用できます。
-
送信側が制御下にない場合。
-
メッセージが到着したときに .exe ファイルまたは COM コンポーネントをトリガする必要がある場合。
-
メッセージ フォーマットが ActiveX である可能性がある場合。
-
受信側の機能を COM Interop で呼び出される .NET ベースのコンポーネントとして実装する準備ができている場合。
独自のレシーバ
独自のレシーバを開発すると、フォーマット、再試行時の動作、例外管理などを自由に制御できます。ただし、独自のレシーバ サービスを開発するには、非同期通信の管理、マルチスレッド処理、セキュリティ、例外管理に関する高いスキルが求められるため、必ずしも推奨しません。独自のレシーバ サービスを開発する場合は、展開前に徹底したテスティングを行ってください。
その他の非同期テクノロジ
メッセージ キューの他にも、Visual Studio .NET を使用して XML Web サービス プロキシを開発するという方法もあります。このプロキシを使用すると、Begin<メソッド名> という形のメソッドを使用し、コールバック関数を指定することによって、Web サービスが公開するメソッドを非同期に呼び出すことができます。
また、コールバックを使用して、.NET リモート処理チャネルによるメソッドの非同期呼び出しを実装することもできます。.NET リモート処理を使用して非同期処理を実装する方法の詳細については、MSDN ライブラリに公開されている .NET Framework SDK の「非同期リモート処理」を参照してください。
同期通信の各種テクノロジ
.NET では、同期通信についてさまざまなオプションが用意されています。各オプションは、エンド ポイント (例 : IIS)、プロトコル (例 : HTTP)、フォーマット (例 : SOAP) の組み合わせとして定義されます。可能な組み合わせは、"チャネル" と呼び、実際の通信はチャネルを通じて行われます。エンド ポイント、プロトコル、フォーマットを独自に組み合わせることによって、独自のチャネルを実装することもできます。
チャネルにはさまざまな属性があります。どの属性を重要視するのかは、コンポーネントの相互通信に依存します。具体的には、次のような属性があります。
-
トランザクション コンテキスト フローの機能
-
多様なプラットフォームの多様なクライアントへの対応
-
セキュリティ機能 (認証、承認、チャネルの暗号化)
-
ネットワーク インフラストラクチャに対するプロトコル要件
-
送信するデータの内容とサイズによって決まる効率性
諸条件に合った同期通信のテクノロジを選択するには、以下の質問について考えてみてください。
-
トランザクションまたは Windows セキュリティ コンテキストのフローは必要ですか。
必要な場合は、DCOM を使用してください。エンド ポイントは Enterprise Services にホストし、トランザクションを活用できるようにします。呼び出し先は、SecurityCallContext クラスを使用することによって、コンポーネントの呼び出し元の ID を知ることができます。
必要ない場合は、質問 2 に移ってください。
-
幅広い対応が必要ですか。
標準化された手法を用いてサービスを幅広く公開する必要がある場合は、SOAP と HTTP を使用して XML Web サービスを実装します。Windows 2000 で Web サービスを公開するには、ASP.NET の .asmx ファイルを使用する方法と、HTTP/SOAP リモート処理チャネルを使用する方法があります。質問 4 に移ってください。
必要ない場合は、質問 3 に移ってください。
-
呼び出し元を認証する必要はありますか。
トランザクション、セキュリティ フロー、幅広い公開のいずれも必要ない場合は、.NET リモート処理チャネルを使用できます。HTTP 経由で呼び出しを受けた場合、.NET リモート処理で呼び出し元を認証するには、IIS が必要です。したがって、認証が必要な場合は、IIS がエンド ポイントとして必要となります。
認証が必要ない場合は、任意のプロセスに .NET リモート処理チャネルをホストして利用できます。
-
ビジネス機能の公開にファサード コードを実装する必要がありますか。
追加の検証、変換、例外のキャッチを実行するために、ビジネス ロジックを特別なファサードでラッピングする必要がある場合は、ASP.NET の Web サービスを使用すると、SOAP から呼び出すことができる機能を簡単に実装できます。
拡張用のファサード層が必要ない場合は、型をそのまま Web サービスとして公開できます。Enterprise Services のクラスを直接公開することはできません。サービス コンポーネントとしてビジネス コンポーネントを作成した場合は、Windows 2000 で ASP.NET の Web サービスまたはリモート処理クラスを使用してファサード層を作成できます。
メモ 最新の修正プログラムが組み込まれた DCOM を使用すると、既知の 1 ポートだけを通じて通信を確立できるようになります。詳細については、以下の Microsoft サポート技術情報の Knowledge Base の文書を参照してください。
154596 「RPC の動的ポートを変更する方法」
312960 「COM+ アプリケーションのエンド ポイントを静的にできない」
XML Web サービスを使用するのか、.NET リモート処理を使用するのかの詳細については、MSDN ライブラリに公開されている .NET Framework SDK の「.NET での通信オプションの選択」を参照してください。
.NET リモート処理の詳細については、以下の資料を参照してください。
通信に関するガイドライン
サービスとアプリケーションを実装するときは、以下のガイドラインを参考にしてください。
-
キューとキャッシュを使用して呼び出しチェーンをできる限り分断する。これによって、ソリューション全体の拡張性と可用性を高めることができます。
-
非同期の境界をユーザー、サービス インターフェイス、サービス エージェントに近いところに置き、サービスを外部要因から切り離す。
-
機能を同期処理として公開する必要がある場合は、内部的には非同期の処理をラッピングできないかどうかを検討する。 この詳細については、次のセクションを参照してください。
非同期通信を同期要求にカプセル化する
アプリケーションの設計としては、できる限り一貫して非同期型の通信を使用することが望ましいといえます。ただし、場合によっては、クライアントにとって同期的に応答を受け取ることができた方が合理的であったり、これが必須であることもあります。また、呼び出し先のサービスの応答時間が期待値に達しない場合に限って完全非同期型の設計を採用するという方法も考えられます。このパターンは、ほとんどの場合、サービス エージェントの実装時に適用されます。
非同期型を採用しながら、呼び出し元に対しては同期型のインターフェイスを提供するようコンポーネントを設計することもできます。これを実現するためには、次のような基本設計を行います。
-
呼び出し元が同期型の要求をコンポーネントに送信します。
-
コンポーネントは要求を受け取ったら、要求を一意に特定できる識別子または Cookie を作成します。可能であれば、データベースにエントリとして格納します。
-
サーバーが非同期型として要求をサービスに送信します。
-
コンポーネントは一定のタイムアウト条件の下、応答メッセージを待機します。
-
コンポーネントが想定時間内にメッセージを受信したら、応答メッセージを作成して、同期型の呼び出し元に返します。
-
コンポーネントが時間内にメッセージを受信できなかった場合は、要求 ID を付けた "定型" の応答を呼び出し元に返すか、呼び出し元が処理できる例外を送信します。サーバー コンポーネントはこの時点で動作を停止します。
-
結果を呼び出し元に渡すには、次の 2 つの選択肢があります。
-
一定時間経過後 (数秒後または数分後) に、呼び出し側が要求 ID に基づいてサーバー コンポーネントを呼び出し、結果をポーリングします。呼び出し元がユーザーの場合は、通常、グラフィック アニメーションを画面に表示して待機状態であることを示します。
-
サーバー側が非同期のメカニズムを使用して呼び出し元に通知を送信します。この場合は、電子メール、Windows Messenger、ページャー メッセージなどを使用するか、メッセージをクライアントに返し、クライアントが結果を画面に表示できるようにします。アプリケーションまたはユーザーには、電子メール アドレスやメッセージ キューのメッセージ パスなど、アドレス指定できる "メッセージ シンク" が割り当てられている必要があります。メッセージ キューを使用している場合は、相関 ID を使用して応答メッセージのマッピングを適用する必要があります。
通信のフォーマット、スキーマ、プロトコル
データの送受信に使用するフォーマット、およびデータを交換するときのスキーマは、アプリケーションの通信を設計するうえで重要なポイントとなります。
フォーマットおよびスキーマを左右する要素としては、次のものが考えられます。
-
通信のエンド ポイントの両端が制御下にあるかどうか。両方とも制御下にある場合は、相互運用性を犠牲にし、パフォーマンスと機能性 (セキュリティ、トランザクション フローなど) を優先して書式とプロトコルを選択できます。通信先がアプリケーション内のコンポーネントで、すべての層が密に関連しているか、密に結合している場合は、この手法を採用できます。
-
組織の内外を問わず、外部の呼び出し元からアクセスできるようにするかどうか。アクセスできるようにする場合は、広く採用されている標準的なプロトコル (例 : TCP)、フォーマット (例 : SOAP)、スキーマ (例 : www.uddi.org に登録されているスキーマ) をできる限り使用してください。特に、サービス インターフェイスとサービス エージェントの場合はこの点が重要です。通信先のサービスや組織内の通信が標準化されたメカニズムを使用していない場合は、エンド ポイント間にブリッジや追加の変換層を設けることを検討してください。
将来について
サービス間通信の標準化は業界でも急速に進んでおり、Microsoft は次世代の製品で、標準的なメカニズムを通じてビジネス機能をさらに簡単に公開、利用できるようにしていきます。
これらのテクノロジに関する将来の見通しについては、以下の資料を参考にしてください。
次章では
この章では、セキュリティ、運用管理、通信に関するポリシーについて説明してきました。「第 4 章 物理的な展開と運用上の要件」では、アプリケーションを物理的な環境に展開する際の各種戦略について解説し、運用要件を満たすための方法について説明します。
ご意見、お問い合わせ、およびサポート
このガイドに関する質問、ご意見、ご提案などがございましたら、devfdbck@microsoft.com までご連絡ください。