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のユーザとグループの管理画面で変更すると、例外が発生せず、処理が実行されます。