冒充客户

模拟示例演示如何在服务中模拟调用方应用程序,以便服务代表调用方访问系统资源。

此示例基于 自托管 示例。 服务和客户端配置文件与 自承载 示例的配置文件相同。

注释

本示例的设置过程和生成说明位于本主题末尾。

服务代码已被修改,这样服务中的 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以下示例代码中显示的方法是显示调用方标识的实用工具函数。

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枚举来指定服务所用的模拟级别。 枚举支持以下值: NoneAnonymousIdentificationImpersonationDelegation。 若要在使用 Windows ACL 保护的本地计算机上访问系统资源时执行访问检查,必须设置为 Impersonation模拟级别,如以下示例代码所示。

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

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

运行示例时,作请求和响应会显示在服务和客户端控制台窗口中。 在每个控制台窗口中按 Enter 可以关闭服务和客户端。

注释

服务必须在管理帐户下运行,或者必须向其运行的帐户授予向 HTTP 层注册 http://localhost:8000/ServiceModelSamples URI 的权限。 可以通过使用 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 示例中的说明进行操作。

  4. 为了演示服务模拟调用方,请在与服务所运行帐户不同的帐户下运行客户端。 为此,请在命令提示符处键入:

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

    然后系统会提示输入密码。 输入之前指定的帐户的密码。

  5. 运行客户端时,请注意它在用不同的凭据运行前后的标识。