次の方法で共有


トークン プロバイダー

このサンプルでは、カスタム トークン プロバイダーを実装する方法を示します。 Windows Communication Foundation (WCF) のトークン プロバイダーは、セキュリティ インフラストラクチャに資格情報を提供するために使用されます。 一般に、トークン プロバイダーはターゲットを調べ、適切な資格情報を発行して、セキュリティ インフラストラクチャがメッセージをセキュリティで保護できるようにします。 WCF には、既定の資格情報マネージャー トークン プロバイダーが付属しています。 WCF には、CardSpace トークン プロバイダーも付属しています。 カスタム トークン プロバイダーは、次の場合に役立ちます。

  • これらのトークンプロバイダーが対応できないクレデンシャルストアがある場合。

  • ユーザーが詳細を提供した時点から WCF クライアント フレームワークが資格情報を使用するタイミングまで、資格情報を変換するための独自のカスタム メカニズムを提供する場合。

  • カスタム トークンを構築する場合。

このサンプルでは、ユーザーからの入力を別の形式に変換するカスタム トークン プロバイダーを構築する方法を示します。

要約すると、このサンプルでは次の例を示します。

  • クライアントがユーザー名とパスワードのペアを使用して認証する方法。

  • カスタム トークン プロバイダーを使用してクライアントを構成する方法。

  • ユーザー名とパスワードが一致することを検証するカスタム UserNamePasswordValidator を使用して、サーバーがパスワードを使用してクライアント資格情報を検証する方法。

  • サーバーの X.509 証明書を使用してクライアントによってサーバーが認証される方法。

このサンプルでは、カスタム トークン認証プロセスの後に呼び出し元の ID にアクセスする方法も示します。

サービスは、App.config 構成ファイルを使用して定義された、サービスと通信するための単一のエンドポイントを公開します。 エンドポイントは、アドレス、バインディング、およびコントラクトで構成されます。 バインディングは、既定でメッセージ セキュリティを使用する標準 wsHttpBindingで構成されます。 このサンプルでは、クライアント ユーザー名認証を使用する標準 wsHttpBinding を設定します。 サービスでは、serviceCredentials の動作を使用してサービス証明書も構成されます。 serviceCredentials の動作を使用すると、サービス証明書を構成できます。 サービス証明書は、サービスを認証し、メッセージ保護を提供するためにクライアントによって使用されます。 次の構成では、次のセットアップ手順で説明するように、サンプルセットアップ中にインストールされた localhost 証明書を参照します。

<system.serviceModel>
    <services>
      <service
          name="Microsoft.ServiceModel.Samples.CalculatorService"
          behaviorConfiguration="CalculatorServiceBehavior">
        <host>
          <baseAddresses>
            <!-- configure base address provided by host -->
            <add baseAddress ="http://localhost:8000/servicemodelsamples/service"/>
          </baseAddresses>
        </host>
        <!-- use base address provided by host -->
        <endpoint address=""
                  binding="wsHttpBinding"
                  bindingConfiguration="Binding1"
                  contract="Microsoft.ServiceModel.Samples.ICalculator" />
      </service>
    </services>

    <bindings>
      <wsHttpBinding>
        <binding name="Binding1">
          <security mode="Message">
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>

    <behaviors>
      <serviceBehaviors>
        <behavior name="CalculatorServiceBehavior">
          <serviceDebug includeExceptionDetailInFaults="False" />
          <!--
        The serviceCredentials behavior allows one to define a service certificate.
        A service certificate is used by a client to authenticate the service and provide message protection.
        This configuration references the "localhost" certificate installed during the setup instructions.
        -->
          <serviceCredentials>
            <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

クライアント エンドポイント構成は、構成名、サービス エンドポイントの絶対アドレス、バインディング、コントラクトで構成されます。 クライアント バインドは、適切な Mode とメッセージ clientCredentialTypeで構成されます。

<system.serviceModel>
  <client>
    <endpoint name=""
              address="http://localhost:8000/servicemodelsamples/service"
              binding="wsHttpBinding"
              bindingConfiguration="Binding1"
              contract="Microsoft.ServiceModel.Samples.ICalculator">
    </endpoint>
  </client>

  <bindings>
    <wsHttpBinding>
      <binding name="Binding1">
        <security mode="Message">
          <message clientCredentialType="UserName" />
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
</system.serviceModel>

次の手順では、カスタム トークン プロバイダーを開発し、WCF セキュリティ フレームワークと統合する方法を示します。

  1. カスタム トークン プロバイダーを記述します。

    このサンプルでは、ユーザー名とパスワードを取得するカスタム トークン プロバイダーを実装しています。 パスワードは、このユーザー名と一致する必要があります。 このカスタム トークン プロバイダーはデモンストレーションのみを目的としており、実際のデプロイには推奨されません。

    このタスクを実行するために、カスタム トークン プロバイダーは SecurityTokenProvider クラスを派生させ、 GetTokenCore(TimeSpan) メソッドをオーバーライドします。 このメソッドは、新しい UserNameSecurityTokenを作成して返します。

    protected override SecurityToken GetTokenCore(TimeSpan timeout)
    {
        // obtain username and password from the user using console window
        string username = GetUserName();
        string password = GetPassword();
        Console.WriteLine("username: {0}", username);
    
        // return new UserNameSecurityToken containing information obtained from user
        return new UserNameSecurityToken(username, password);
    }
    
  2. カスタム セキュリティ トークン マネージャーを記述します。

    SecurityTokenManagerSecurityTokenProvider メソッドで渡される特定のSecurityTokenRequirementCreateSecurityTokenProviderを作成するために使用されます。 セキュリティ トークン マネージャーは、トークン認証子とトークン シリアライザーの作成にも使用されますが、このサンプルでは説明しません。 このサンプルでは、カスタム セキュリティ トークン マネージャーは、 ClientCredentialsSecurityTokenManager クラスから継承し、渡されたトークン要件がユーザー名プロバイダーが要求されたことを示す場合にカスタム ユーザー名トークン プロバイダーを返す CreateSecurityTokenProvider メソッドをオーバーライドします。

    public class MyUserNameSecurityTokenManager : ClientCredentialsSecurityTokenManager
    {
        MyUserNameClientCredentials myUserNameClientCredentials;
    
        public MyUserNameSecurityTokenManager(MyUserNameClientCredentials myUserNameClientCredentials)
            : base(myUserNameClientCredentials)
        {
            this.myUserNameClientCredentials = myUserNameClientCredentials;
        }
    
        public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
        {
            // if token requirement matches username token return custom username token provider
            // otherwise use base implementation
            if (tokenRequirement.TokenType == SecurityTokenTypes.UserName)
            {
                return new MyUserNameTokenProvider();
            }
            else
            {
                return base.CreateSecurityTokenProvider(tokenRequirement);
            }
        }
    }
    
  3. カスタム クライアント資格情報を書き込みます。

    クライアント資格情報クラスは、クライアント プロキシ用に構成された資格情報を表すために使用され、トークン認証子、トークン プロバイダー、トークン シリアライザーを取得するために使用されるセキュリティ トークン マネージャーを作成します。

    public class MyUserNameClientCredentials : ClientCredentials
    {
        public MyUserNameClientCredentials()
            : base()
        {
        }
    
        protected override ClientCredentials CloneCore()
        {
            return new MyUserNameClientCredentials();
        }
    
        public override SecurityTokenManager CreateSecurityTokenManager()
        {
            // return custom security token manager
            return new MyUserNameSecurityTokenManager(this);
        }
    }
    
  4. カスタム クライアント資格情報を使用するようにクライアントを構成します。

    クライアントがカスタム クライアント資格情報を使用するために、サンプルは既定のクライアント資格情報クラスを削除し、新しいクライアント資格情報クラスを提供します。

    static void Main()
    {
        // ...
           // Create a client with given client endpoint configuration
          CalculatorClient client = new CalculatorClient();
    
          // set new credentials
           client.ChannelFactory.Endpoint.Behaviors.Remove(typeof(ClientCredentials));
         client.ChannelFactory.Endpoint.Behaviors.Add(new MyUserNameClientCredentials());
       // ...
    }
    

サービスで、呼び出し元の情報を表示するには、次のコード例に示すように PrimaryIdentity を使用します。 Currentには、現在の呼び出し元に関する要求情報が含まれています。

static void DisplayIdentityInformation()
{
    Console.WriteLine("\t\tSecurity context identity  :  {0}",
        ServiceSecurityContext.Current.PrimaryIdentity.Name);
}

サンプルを実行すると、操作要求と応答がクライアント コンソール ウィンドウに表示されます。 クライアント ウィンドウで Enter キーを押して、クライアントをシャットダウンします。

Batch ファイルのセットアップ

このサンプルに含まれる Setup.bat バッチ ファイルを使用すると、サーバー証明書ベースのセキュリティを必要とするセルフホステッド アプリケーションを実行するように、関連する証明書を使用してサーバーを構成できます。 このバッチ ファイルは、コンピューター間で動作するように、またはホストされていないケースで動作するように変更する必要があります。

次に、適切な構成で実行するように変更できるように、バッチ ファイルのさまざまなセクションの概要を示します。

  • サーバー証明書の作成。

    Setup.bat バッチ ファイルの次の行は、使用するサーバー証明書を作成します。 %SERVER_NAME%変数は、サーバー名を指定します。 この変数を変更して、独自のサーバー名を指定します。 このバッチ ファイルの既定値は localhost です。

    echo ************
    echo Server cert setup starting
    echo %SERVER_NAME%
    echo ************
    echo making server cert
    echo ************
    makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
    
  • クライアントの信頼された証明書ストアへのサーバー証明書のインストール:

    Setup.bat バッチ ファイル内の次の行は、クライアントの信頼できるユーザー ストアにサーバー証明書をコピーします。 Makecert.exe によって生成された証明書はクライアント システムによって暗黙的に信頼されないため、この手順が必要です。 クライアントの信頼されたルート証明書 (Microsoft が発行した証明書など) にルート化された証明書が既にある場合、クライアント証明書ストアにサーバー証明書を設定するこの手順は必要ありません。

    certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
    

Setup.bat バッチ ファイルは、Windows SDK コマンド プロンプトから実行するように設計されています。 これは、MSSDK 環境変数が SDK がインストールされているディレクトリを指している必要があります。 この環境変数は、Windows SDK コマンド プロンプト内で自動的に設定されます。

サンプルを設定してビルドするには

  1. Windows Communication Foundation サンプル One-Time セットアップ手順を実行していることを確認します。

  2. ソリューションをビルドするには、「 Windows Communication Foundation サンプルのビルド」の手順に従います。

同じコンピューターでサンプルを実行するには

  1. 管理者特権で開いた Visual Studio コマンド プロンプト内のサンプル インストール フォルダーから Setup.bat を実行します。 これにより、サンプルの実行に必要なすべての証明書がインストールされます。

    Setup.bat バッチ ファイルは、Visual Studio コマンド プロンプトから実行するように設計されています。 Visual Studio コマンド プロンプト内で設定された PATH 環境変数は、Setup.bat スクリプトに必要な実行可能ファイルを含むディレクトリを指します。

  2. service\bin から service.exe を起動します。

  3. \client\bin から Client.exe を起動します。 クライアント アクティビティがクライアント コンソール アプリケーションに表示されます。

  4. ユーザー名のプロンプトで、ユーザー名を入力します。

  5. パスワード プロンプトで、ユーザー名プロンプトに入力されたのと同じ文字列を使用します。

  6. クライアントとサービスが通信できない場合は、「WCF サンプルのトラブルシューティングのヒント」を参照してください。

複数のコンピューターでサンプルを実行するには

  1. サービス バイナリのサービス コンピューター上にディレクトリを作成します。

  2. サービス プログラム ファイルをサービス コンピューター上のサービス ディレクトリにコピーします。 また、Setup.bat ファイルと Cleanup.bat ファイルをサービス コンピューターにコピーします。

  3. コンピューターの完全修飾ドメイン名を含むサブジェクト名を持つサーバー証明書が必要です。 Service.exe.config ファイルは、この新しい証明書名を反映するように更新する必要があります。 Setup.bat バッチ ファイルを変更することで、サーバー証明書を作成できます。 setup.bat ファイルは、管理者特権で開かれた Visual Studio の開発者コマンド プロンプトから実行する必要があることに注意してください。 変数 %SERVER_NAME% 、サービスのホストに使用されるコンピューターの完全修飾ホスト名に設定する必要があります。

  4. サーバー証明書をクライアントの CurrentUser-TrustedPeople ストアにコピーします。 クライアントの信頼された発行者によってサーバー証明書が発行されている場合は、この操作を行う必要はありません。

  5. サービス コンピューター上の Service.exe.config ファイルで、localhost ではなく完全修飾コンピューター名を指定するようにベース アドレスの値を変更します。

  6. サービス コンピューターで、コマンド プロンプトから service.exe を実行します。

  7. クライアント プログラム ファイルを、言語固有のフォルダーの下にある \client\bin\ フォルダーからクライアント コンピューターにコピーします。

  8. クライアント コンピューター上の Client.exe.config ファイルで、サービスの新しいアドレスと一致するようにエンドポイントのアドレス値を変更します。

  9. クライアント コンピューターで、コマンド プロンプト ウィンドウから Client.exe を起動します。

  10. クライアントとサービスが通信できない場合は、「WCF サンプルのトラブルシューティングのヒント」を参照してください。

サンプルの実行後にクリーンアップするには

  1. サンプルの実行が完了したら、samples フォルダーで Cleanup.bat を実行します。