ワークフロー優先とセキュリティのサンプル
メモ : |
---|
このサンプルをビルドして実行するには、.NET Framework Version 3.5 をインストールする必要があります。プロジェクト ファイルとソリューション ファイルを開くには、Visual Studio 2008 が必要です。 |
このサンプルでは、以下に示すワークフロー サービス内の 2 つの重要な機能を示します。
作成サービスの "ワークフロー優先" メソッド
サービスの作成は、ワークフローを使った 2 とおりの方法で行うことができます。1 つは、"コントラクト優先" の作成方法で、コントラクトが既に存在し、ワークフローがコントラクトを実装する場合が当てはまります。もう 1 つはワークフロー優先の作成方法で、ワークフローの作成と同時にコントラクトも作成されます。ワークフロー デザイナは、実質的にコントラクト デザイナとして機能します。このサンプルでは、ワークフローの作成に伴って電卓コントラクトが作成されます。
このサンプルでは、ワークフロー優先のマークアップが SequentialCalculatorService.xoml ファイルに実装されます。ワークフロー優先プログラミングの基盤となるプログラミング モデルについて理解するには、他のワークフロー サンプルのマークアップとこのマークアップを比較してください。
次のサンプル コードでは、サンプル内の Receive アクティビティのマークアップを示します。
<ns0:ReceiveActivity x:Name="ReceiveAdd" OperationValidation="ValidateOwner" CanCreateInstance="True"> <ns0:ReceiveActivity.ServiceOperationInfo> <ns0:OperationInfo PrincipalPermissionRole="Administrators" Name="Add" ContractName="ICalculator"> <ns0:OperationInfo.Parameters> <ns0:OperationParameterInfo Attributes="In" ParameterType="{x:Type p15:Int32}" Name="value" Position="0" xmlns:p15="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <ns0:OperationParameterInfo Attributes="Out" ParameterType="{x:Type p15:Int32}" Name="returnValue" Position="1" xmlns:p15="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> </ns0:OperationInfo.Parameters> </ns0:OperationInfo> </ns0:ReceiveActivity.ServiceOperationInfo> <ns0:ReceiveActivity.ParameterBindings> <WorkflowParameterBinding ParameterName="value"> <WorkflowParameterBinding.Value> <ActivityBind Name="SequentialCalculatorService" Path="inputValue" /> </WorkflowParameterBinding.Value> </WorkflowParameterBinding> <WorkflowParameterBinding ParameterName="returnValue"> <WorkflowParameterBinding.Value> <ActivityBind Name="SequentialCalculatorService" Path="currentValue" /> </WorkflowParameterBinding.Value> </WorkflowParameterBinding> </ns0:ReceiveActivity.ParameterBindings> <CodeActivity x:Name="DoAdd" ExecuteCode="Add" /> </ns0:ReceiveActivity>
この Receive アクティビティには外部コントラクト型への参照が含まれず、コントラクトは Receive アクティビティそのものの内部で定義されています。Receive アクティビティの
OperationInfo
ブロックは、コントラクト名と操作名の両方を表します。これらの名前は、コントラクトを定義する型への参照が含まれないリテラル文字列です。サンプルを実行すると、ワークフロー サービス ホストによって、サービスの説明を作成するためにこの定義が使用されます。サービス クライアントをこの目的で作成するには、ServiceModel Metadata Utility Tool (Svcutil.exe) を使用します。
ワークフロー サービスのセキュリティ
ワークフロー サービスには、サービスに対する 2 つのレベルのセキュリティが用意されています。最初のレベルでは、操作に対するプリンシパル アクセス許可のセキュリティを指定します。サービス ランタイムは、このアクセス許可をチェックしてから、メッセージをワークフローに配布します。プリンシパル アクセス許可のセキュリティを満たしていないメッセージは、ワークフローに配布されません。2 番目のレベルは、"操作検証条件" で、Receive アクティビティに割り当てることができます。操作検証条件は、Receive アクティビティによってメッセージが受信されると実行されます。メッセージがこの操作検証条件を満たしていない場合は、エラーがクライアントに送信されて、メッセージが削除され、ワークフローは失敗します。
OperationInfo 要素の PrincipalPermissionRole 属性は、管理者グループのユーザーにしかこの操作の呼び出しを許可しないことを指定します。
Receive アクティビティの OperationValidation 属性は、検証条件として実行するためのコード ハンドラを参照します。このサンプルでは、最初の Receive アクティビティに対して PrincipalPermissionRole 属性が設定されているので、管理者グループのユーザーのみが最初の操作を呼び出すことができます。このワークフローでは、
ReceiveAdd
Receive アクティビティのプロパティ CanCreateInstance が true に設定されています。つまり、このサービスのインスタンスは、管理者グループのユーザーによって追加操作が呼び出されると作成されます。後続の受信操作では、操作を呼び出したプリンシパルがインスタンスを作成したプリンシパルと同じであるかどうかが OperationValidation 条件によってチェックされます。このシナリオでは、インスタンスを開始したユーザーが以降のメッセージを送信できます。次のサンプルでは、これを実行する OperationValidation 条件のコードを示します。
private void ValidateOwner(object sender, OperationValidationEventArgs e) { if (string.IsNullOrEmpty(owner)) { owner = ExtractCallerName(e.ClaimSets); e.IsValid = true; Console.WriteLine("Owner: " + owner); } if (owner.Equals(ExtractCallerName(e.ClaimSets))) e.IsValid = true; } private string ExtractCallerName(ReadOnlyCollection<ClaimSet> claimSets) { string owner = string.Empty; foreach (ClaimSet claims in claimSets) { foreach (Claim claim in claims) { if (claim.ClaimType.Equals(ClaimTypes.Name) && claim.Right.Equals(Rights.PossessProperty)) { owner = claim.Resource.ToString(); break; } } } return owner; }
上記に示す
ValidateOwner
メソッドは、OperationValidationEventArgs
引数の一部としてクレーム セットを提供します。メッセージの検証は、これらのクレーム セットを使用して行われます。この時点では、実際のメッセージ本文パラメータはまだ使用できません。ExtractCallerName
メソッドは、Name クレームから呼び出し元の名前を抽出して、格納します。それ以降の要求では、呼び出し元の名前を受信メッセージの Name クレームと照合することによって、最初のメッセージの送信者 (インスタンス作成を開始したユーザー) と後続メッセージの送信者が同じであるかどうかが確認されます。
プロジェクトを設定、ビルド、および実行するには
「Windows Communication Foundation サンプルの 1 回限りのセットアップの手順」に記載されたセットアップ手順を実行します。
「Windows Communication Foundation サンプルの 1 回限りのセットアップの手順」に示した Createstores.cmd スクリプトを実行します。
ソリューションをビルドします。
管理者グループのユーザーとしてサンプルを実行します。サービス実行可能ファイル、クライアント実行可能ファイルの順に実行します。Windows Vista を使用している場合は、実行可能ファイルを右クリックしてから [管理者として実行] をクリックします。サンプルが最後まで実行されます。
別のユーザー ID を使用してサンプルを実行することもできます (別の ID を使用して実行する場合は、実行アカウントを指定するコマンドを使用します)。使用する ID が管理者グループに所属しない場合、サービスはエラーを返します。
別々のコンピュータでサンプルを実行するには
サービスおよびクライアントの構成ファイルを編集し、エンドポイントのアドレスのサーバー名が変更されていることを確認します。サーバー名を
localhost
からサービスを実行するコンピュータ名に変更します。サービスはポート 8888 を使用するため、ファイアウォールのこのポートを開く必要があります。Windows のコントロールパネルから、[Windows ファイアウォール] をクリックします。[ポートの追加] をクリックし、ポート 8888 を追加します。また、既定のポートでサービスを実行することもできます。この場合は、エンドポイントのアドレスから [:8888] を削除します。
クライアントの構成ファイルを編集し、
<endpoint>
要素の子として次の要素を追加します。<identity> <UserPrincipalName value=”*@<Domain Name in which your server is running” /> </identity>
ドメイン名を決定するために、サービスを実行しようとしているコンピュータでサービスを起動します。他のコンピュータのコマンド プロンプト ウィンドウで次のコマンドを実行します。
svcutil.exe http://<serverName>:8888/servicehost/Calculator.svc
このコマンドにより .cs ファイルと output.config ファイルが生成されます。構成ファイルの
<endpoint>
要素で、<identity>
要素をクライアントの構成ファイルにコピーします。
Copyright © 2007 by Microsoft Corporation.All rights reserved.