BasicHttpBindingでBasic認証を実装します。今回は通信データは保護しません。https通信を行う方法はWCF Sample 009 : BasicHttpBindingでトランスポートレベルセキュリティを実装する を参照して下さい。Basic認証を使用することで、異なるセキュリティドメインにある認証が必要なサービスを呼び出す処理を記述できるようにまります。BasicHttpBindingはデフォルトのセキュリティ設定ではBasicHttpSecurityMode.Noneとなっているため、匿名ユーザとしてサービスメソッド上で認識されます。サービスメソッド内で、System.ServiceModel.OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Nameにアクセスすると、ブランクになっていることが確認できます。

動作確認環境は次のとおりです。

  • Windows Vista Enterprise(スタンドアロン環境,WCFサービス,WCFクライアント同一OS上で確認)
  • 開発環境 Visual Studio 2008 Professional
  • .NET 3.5

1.ソリューションの作成

Visual Studio 2008の[File]メニュー→[New]→[Project]から空のソリューションを新規作成する。ソリューション名は仮にWCFSample010とします。次に WCFサンプル再作成(ブラッシュアップ) から以下の3つのプロジェクトをWCFSample010のソリューションのフォルダ直下にコピーし、WCFSample010に既存のプロジェクトとして追加します。

  • WPFSample.WPFHost
  • WPFSample.ProductService
  • WPFSample.ConsoleClient

WCFホストとWCFクライアントをデバッグ時に起動できるように、ソリューションを右クリックし、プロパティを選択後、表示されるダイアログでMultiple Startup projectにWPFSample.WPFHostとWPFSample.ConsoleClinetをStartプロジェクトを指定します。

2.Basic認証の構成

WPFHostのApp.configをWPF Service Configuration Editorで編集します。Configuration Editorに右側ペインのBindingsを右クリック→[New Binding Configuration]をクリック
続いて表示されるダイアログでbasicHttpBindingを選択してOKボタンをクリックしダイアログを閉じます。右側のペインのNameをProductServiceBasicHttpBindingとセットし、Securityタブをクリックし、TransportClientCredentialTypeをNoneからBasicに変更します。同じペインのModeをTransportCredentialOnlyにセットする。

 

Basic認証にすると、クライアントから送信されるユーザ名,パスワードを使用してクライアントを認証するようになりますが、TransportCredentialOnlyの場合はデータ自体は暗号化されません。データを暗号化したい場合はhttpsで通信を行います、ModeはTransportに設定します。今回は資格情報を送信するだけで、暗号化しないので、TransportCredentialOnlyを指定しています。httpsにする場合はhttpsを構成するサンプルを参照

次に、左側ペインを[Services]→[WCFSample.ProductService.ProductService]→[Endpoints]と展開し(Empty Name)を選択する。
右側ペインのBindingConfigurationのプロパティにProductServiceBasicHttpBindingを選択します。

設定は以上です。上書き保存してWCF Service Configuration Editorを終了します。

この状態でソリューションを実行するとエラーが発生し次の例外が発生します。

 

例外 MessageSecurityException
エラーメッセージ The HTTP request is unauthorized with client authentication scheme 'Anonymous'.
The authentication header received from the server was 'Basic realm=""'.

 

 

3.WCFクライアントの構成変更

3.1構成ファイルの変更

ConsoleClientのApp.configをWCF Service Configuration Editorで編集します。左側ペインのBindings→BasicHttpBinding_ProductServiceを選択します。右側ペインのSecurityタブを選択し、ModeをTransportCredentialOnly, TransportCredentialTypeをBasicに設定します。(下図参照)

 

 

上書き保存して、Service Editorを閉じます。

3.2プログラムの変更

プロキシメソッドに資格情報をセットするようにクライアントプログラムを変更します。仮に実行環境のOSのマシン名WCFDEVPCとし、ローカルユーザ,パスワードが以下のユーザが存在するとします。

 

マシン名 WCFDEVPC
ユーザ名 WCFTestUser
パスワード WCFtest001

 

Program.csのMainメソッドの先頭にproxyがサービスメソッドを呼び出す前に資格情報をセットします。以下変更例です。

class Program
    {
        static void Main(string[] args)
        {
            System.Console.WriteLine("WCFサービスホストを起動したら、キーを入力して下さい。");
            System.Console.Read();

            ProductServiceClient proxy = new WCFSample.Client.Proxy.ProductServiceClient("BasicHttpBinding_ProductService");
            // 資格情報追加
            proxy.ClientCredentials.UserName.UserName = @"WCFDEVPC\WCFTestUser";
            proxy.ClientCredentials.UserName.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();
        }
    }

 デバッグ実行させるとプログラムが動作するようになります。

4.実行ユーザの確認

WCFSample.ProductServiceプロジェクトのProductService.csを変更して実行ユーザを確認してみます。WCFSample.ProductServiceプロジェクにSystem.Windows.Forms.dllを追加し、GetProductIDs()メソッドの先頭に以下のコードを追加します。

public List<int> GetProductIDs()
        {
            // 追加
            string user = System.Threading.Thread.CurrentPrincipal.Identity.Name;
            System.Windows.Forms.MessageBox.Show("Thread Identity Name :" + user);

            user = System.ServiceModel.OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name;
            System.Windows.Forms.MessageBox.Show("OperationContext Identity Name : " + user);
            // 追加終了
              ....
         }

ソリューションを実行すると、メッセージボックスが表示され、現在のスレッドの実行ユーザがWCFDEVPC\WCFTestUserと表示され、WCFサービスによって認証されたユーザの名称もWCFDEVPC\WCFTestUserとなっていることが確認できます。

5.Windows認証を行うように構成を変更してみる。

Basic認証からWindows認証に変更するには、WCFサービス,WCFクライアントの構成ファイルの認証方法が記述されているタグのtransport clientCredentialTypeをBasicからWindowsに変更するだけです。変更後ソリューションを実行すると、GetProductIDs()を呼び出したときにログインユーザ名が表示されます。このとき、クライアント側で入力したBasic認証用の資格情報は無視されます。

Windows認証時にログインユーザではなく別のユーザの資格情報で認証されたい場合はproxyメソッドでサービスメソッドを呼び出す前に資格情報をセットします。
以下例
proxy.ClientCredentials.Windows.ClientCredential.Domain = @""  // ドメインユーザの場合、ドメイン名セット
proxy.ClientCredentials.Windows.ClientCredential.UserName = @"WCFDEVPC\WCFTestUser"
proxy.ClientCredentials.Windows.ClientCredential.Password = @"WCFtest001"

以上で終わりです。間違いがありましたらご指摘ください。