如何在 ASP.NET MVC 站点上对用户使用 Windows 身份验证并在后端 WCF 服务上使用 AppPool 用户模拟用户?

How can I use Windows Authentication for Users on a ASP.NET MVC site and impersonate the user using the AppPool user on back-end WCF services?

我们在 .NET 4.5.2 上有一个 ASP.NET MVC 应用程序 运行,它托管在 Windows 10 或 Server 2012R2 上的 IIS 7.5 上。

如何让用户使用他们的 Windows 帐户登录(使用 Windows 身份验证模式)并模拟他们以便将服务帐户(在应用程序池中配置)传递给WCF 服务而不是后端的原始用户 authentication/authorization?

一段时间后,我设法找到了有效的答案和解决方案。

最初似乎IIS 只能将一个用户传递给应用程序。如果您打开 MVC 应用程序的配置编辑器并打开 system.webServer/serverRuntime 部分,您将看到 authenticatedUserOverrideUseAuthenticatedUserUserWorkerProcessUser。这将确定将哪个用户发送到 MVC,您将在 MVC 应用程序的控制器中的 User.Identity 属性下找到 WindowsIdentity。这行不通。

我偶然发现了一篇来自 Microsoft (How to: Impersonate the Original Caller in WCF Calling from a Web Application) 的文章,它为我提供了解决问题的基础。

在文章中他们提到您需要使用 Impersonate() 调用,它看起来像在客户端使用的这样:

using (((WindowsIdentity)User.Identity).Impersonate())
{
    var channelFactory = new ChannelFactory<IService1>("*");

    var proxy = channelFactory.CreateChannel();

    return View((object)proxy.GetName("1"));
}

在服务端,您需要将您的操作标记为模拟:

[OperationBehavior(Impersonation = ImpersonationOption.Required)]

我还添加了 PrincipalPermission 以确保只有服务帐户通过:

[PrincipalPermission(SecurityAction.Demand, Name = "PC-NAME\SvcAccount")]

而且您似乎需要使用 wsHttpBinding 绑定。

<wsHttpBinding>
  <binding name="secure">
    <security mode="TransportWithMessageCredential">
      <transport clientCredentialType="Windows" />
    </security>
  </binding>
</wsHttpBinding>

我让它通过 SSL 工作,它自动将凭据传递给 WCF 服务,但它是原始用户而不是服务帐户,所以我收到来自该服务的授权错误。

经过进一步谷歌搜索,我发现了这个片段,它给了我一个想法:Getting NetworkCredential for current user (C#)

我将我的客户端代码替换为如下所示:

using (System.Security.Principal.WindowsIdentity.GetCurrent().Impersonate())
{
    var channelFactory = new ChannelFactory<IService1>("*");

    var proxy = channelFactory.CreateChannel();

    return View((object)proxy.GetName("1"));
}

那你瞧!有效!服务授权用户(我更改了属性中的名称只是为了确保我不是在做梦)并返回一个值并且 front-end UI 仍然显示登录用户。