WCF Sample 010 Basic認証を実装するの最後でバインディングBasicHttpBindingでWindows認証を行う状態になっているプログラムを引き続き流用して、WCFサービスのメソッドを呼び出すときにアクセス制御を行います。Windowsのセキュリティグループを使用するので、ロール情報の取得はWindows Token Role Providerを使用します。ユーザの認証にWindowsの統合認証を使用していれば、バインディングの種類によらず、使用できます。
確認環境
- Windows Vista Enterprise(スタンドアロン,WCFサービス,WCFクライアント同一OS上)
- 開発環境 Visual Studio 2008 Professional
- .NET 3.5
1.ソリューションの作成
Visual StudioのIDE上で空のソリューションを新規作成します。ソリューション名はWCFSample011とします。WCF Sample 010 Basic認証を実装するで作成した次の3つのプロジェクトをコピーし、既存のプロジェクトとして、ソリューションに追加します。
- WCFSample.ConsoleClient
- WCFSample.ProductService
- WCFSample.WPFHost
ソリューションを右クリック→[Properties]を選択肢、ConsoleClient,WPFHostをMultiple Startup ProjectのStartプロジェクトとして設定します。
2.WPFHostの構成変更
WCF Service Configuration Editorで編集します。左側ペインのAdvanced→Service Behaviors→ProductServiceBehaviorを選択します。左側ペインのAddボタンをクリックしserviceAuthorizationを追加。

左側ペインに追加されたserviceAuthorizationを選択し、右側ペインのPrincipalPermissionModeの値がUseWindowsGroupsであることを確認する。

デフォルトではWCFではロール情報の取得にWindowsTokenRoloeProviderを使用します。サービスのアクセス権限の承認に
Windowsベースのセキュリティグループを使用する場合はserviceAuthorizationを変更する必要はなくデフォルトのままで動作します。
変更内容を保存して終了します。
3.サービスクラスの変更
アクセスユーザがWCFTestUsersグループに属していなければならない場合の設定をProductService.GetProductIDs()にセットしてみます。
[PrincipalPermission(SecurityAction.Demand, Role="WCFTestUsers")]
public List<int> GetProductIDs()
{
List<int> productIDs = new List<int>();
using (DbConnection cn = CreateConnection())
{..}
}
WCFTestUsersグループに所属していないと次の例外が発生します。
例外 | SecurityException |
メッセージ | Request for principal permission failed. |
プログラム上でチェックする場合。Windows統合認証のとき限定
// サービスメソッド内で以下のようにロールを確認する
System.Security.Principal.WindowsIdentity identity = OperationContext.Current.ServiceSecurityContext.WindowsIdentity;
WindowsPrincipal principal = new WindowsPrincipal(identity);
if (!principal.IsInRole("WCFTestUsers"))
{
throw new System.Security.SecurityException("Access Denied");
}
4.動作確認
クライアントプログラムを変更して、ログインしているユーザではなく以下のユーザとしてWCFサービスに資格情報を送信してみます。
マシン名 | WCFDEVPC |
ユーザ名 | WCFTestUser |
パスワード | WCFtest001 |
グループ | Users |
Program.csのMainメソッドで先頭を次のように変更する。
static void Main(string[] args) { System.Console.WriteLine("WCFサービスホストを起動したら、キーを入力して下さい。"); System.Console.Read(); ProductServiceClient proxy = new WCFSample.Client.Proxy.ProductServiceClient("BasicHttpBinding_ProductService"); // 資格情報追加 proxy.ClientCredentials.Windows.ClientCredential.Domain = @""; proxy.ClientCredentials.Windows.ClientCredential.UserName = @"WCFDEVPC\WCFTestUser"; proxy.ClientCredentials.Windows.ClientCredential.Password = @"WCFtest001"; int[] productIDs = proxy.GetProductIDs(); foreach (int productID in productIDs) { Console.WriteLine("Product ID: " + productID); Product product = proxy.GetProductByID(productID); Console.WriteLine("Name: " + product.Name); Console.WriteLine("Color: " + product.Color); Console.WriteLine("ListPrice: " + product.ListPrice); } proxy.Close(); Console.WriteLine("終了するにはなにかキーを押してください。"); Console.ReadLine(); } }
ソリューションを実行すると、SecurityExceptionが発生します。
ユーザWCFTestUserがWCFTestUsersに所属するようにWindowsのユーザとグループの管理画面で変更すると、例外が発生せず、処理が実行されます。