次の方法で共有


クライアントの偽装

偽装サンプルでは、サービスが呼び出し元の代わりにシステム リソースにアクセスできるように、サービスで呼び出し元アプリケーションを偽装する方法を示します。

このサンプルは、 セルフホスト サンプルに基づいています。 サービスとクライアントの構成ファイルは、 セルフホスト サンプルのファイルと同じです。

このサンプルのセットアップ手順とビルド手順は、このトピックの最後にあります。

次のサンプル コードに示すように、サービスの Add メソッドが OperationBehaviorAttribute を使用して呼び出し元を偽装するように、サービス コードが変更されました。

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public double Add(double n1, double n2)
{
    double result = n1 + n2;
    Console.WriteLine("Received Add({0},{1})", n1, n2);
    Console.WriteLine("Return: {0}", result);
    DisplayIdentityInformation();
    return result;
}

その結果、実行中のスレッドのセキュリティ コンテキストは、 Add メソッドに入る前に呼び出し元を偽装するように切り替え、メソッドの終了時に元に戻されます。

次のサンプル コードに示す DisplayIdentityInformation メソッドは、呼び出し元の ID を表示するユーティリティ関数です。

static void DisplayIdentityInformation()
{
    Console.WriteLine("\t\tThread Identity            :{0}",
         WindowsIdentity.GetCurrent().Name);
    Console.WriteLine("\t\tThread Identity level  :{0}",
         WindowsIdentity.GetCurrent().ImpersonationLevel);
    Console.WriteLine("\t\thToken                     :{0}",
         WindowsIdentity.GetCurrent().Token.ToString());
    return;
}

サービスの Subtract メソッドは、次のサンプル コードに示すように、命令型呼び出しを使用して呼び出し元を偽装します。

public double Subtract(double n1, double n2)
{
    double result = n1 - n2;
    Console.WriteLine("Received Subtract({0},{1})", n1, n2);
    Console.WriteLine("Return: {0}", result);
    Console.WriteLine("Before impersonating");
    DisplayIdentityInformation();

    if (ServiceSecurityContext.Current.WindowsIdentity.ImpersonationLevel == TokenImpersonationLevel.Impersonation ||
        ServiceSecurityContext.Current.WindowsIdentity.ImpersonationLevel == TokenImpersonationLevel.Delegation)
    {
        // Impersonate.
        using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate())
        {
            // Make a system call in the caller's context and ACLs
            // on the system resource are enforced in the caller's context.
            Console.WriteLine("Impersonating the caller imperatively");
            DisplayIdentityInformation();
        }
    }
    else
    {
        Console.WriteLine("ImpersonationLevel is not high enough to perform this operation.");
    }

    Console.WriteLine("After reverting");
    DisplayIdentityInformation();
    return result;
}

この場合、呼び出し元は呼び出し全体を偽装するのではなく、呼び出しの一部に対してのみ偽装されることに注意してください。 通常、操作全体の偽装を行うよりも、最小限の範囲での偽装をお勧めします。

他のメソッドは呼び出し元を偽装しません。

偽装レベルを Impersonationに設定するようにクライアント コードが変更されました。 クライアントは、 TokenImpersonationLevel 列挙型を使用して、サービスで使用する偽装レベルを指定します。 列挙は、 NoneAnonymousIdentificationImpersonation 、および Delegationの値をサポートしています。 Windows ACL を使用して保護されているローカル コンピューター上のシステム リソースにアクセスするときにアクセス チェックを実行するには、次のサンプル コードに示すように、偽装レベルを Impersonation に設定する必要があります。

// Create a client with given client endpoint configuration
CalculatorClient client = new CalculatorClient();

client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;

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

サービスは、管理アカウントで実行するか、実行するアカウントに、 http://localhost:8000/ServiceModelSamples URI を HTTP レイヤーに登録する権限を付与する必要があります。 このような権限は、Httpcfg.exe ツールを使用して名前空間予約を設定することで付与できます。

Windows Server 2003 を実行しているコンピューターでは、偽装は、Host.exe アプリケーションに偽装特権がある場合にのみサポートされます。 (既定では、このアクセス許可を持つのは管理者だけです)。サービスが実行されているアカウントにこの権限を追加するには、[ 管理ツール] に移動し、[ ローカル セキュリティ ポリシー] を開き、[ ローカル ポリシー] を開 き、[ユーザー権利の割り当て] をクリックし、[ 認証後にクライアントの権限を借用 する] を選択し、[ プロパティ ] をダブルクリックしてユーザーまたはグループを追加します。

サンプルを設定、ビルド、実行するには

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

  2. ソリューションの C# または Visual Basic .NET エディションをビルドするには、「Windows Communication Foundation サンプルのビルド」の手順に従います。

  3. 単一または複数のコンピューター間の構成でサンプルを実行するには、「Windows Communication Foundation Samplesの実行」の手順に従います。

  4. サービスが呼び出し元を偽装していることを示すには、サービスが実行されているアカウントとは異なるアカウントでクライアントを実行します。 これを行うには、コマンド プロンプトで次のように入力します。

    runas /user:<machine-name>\<user-name> client.exe
    

    その後、パスワードの入力を求められます。 前に指定したアカウントのパスワードを入力します。

  5. クライアントを実行するときは、実行前と実行後の ID を異なる資格情報でメモします。