如何使用模拟从 IIS 访问网络资源?

How to use impersonation to access a network resource from IIS?

我有一个 WebApi 应用需要访问另一台机器上的网络共享并打开 Crystal 报告文件。

我正在使用 LogonUserWindowsIdentity.Impersonate 来模拟有权使用此代码(不完整)的网络共享的用户:

SafeTokenHandle safeTokenHandle;

const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_LOGON_INTERACTIVE = 2;

bool returnValue = LogonUser(userName, domainName, userPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle);

if (returnValue == false)
{
    int ret = Marshal.GetLastWin32Error();
    throw new System.ComponentModel.Win32Exception(ret);
}

using (safeTokenHandle)
using (var newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))
using (var impersonatedUser = newId.Impersonate())
{ 
    actionToExecute();
}

例如,在使用托管代码 (System.IO) 列出文件夹或删除文件时,这很有效。但是我需要打开 Crystal 报告文件(我有最新版本),这样做时出现异常:

Access denied

我假设 CR 正在尝试在应用程序池用户的上下文中加载文件。

如果我将应用程序池用户更改为对网络共享具有足够权限的域用户,我可能会实现此目的。但我想避免这种解决方案。

使用 .NET4.6 的新 WindowsIdentity.RunImpersonated 会有所帮助还是会有相同的结果。如果是,是否有办法在提供的用户上下文而不是应用程序池/AppDomain 用户中使 CR 达到 运行?

更新

我通过将 LogonUser 参数更改为 LOGON32_LOGON_NEW_CREDENTIALSLOGON32_PROVIDER_WINNT50 取得了部分成功。然后我测试了以下内容:

  1. 从 VS2017 本地启动项目(以便 WebApi 项目 运行s 在本地 IIS Express 上下文中)并使用我机器上的客户端应用程序访问网络资源。这次测试成功了。

  2. 在单独的机器上发布了 IIS 上的 WebApi 项目。在我的机器上启动客户端 (ClickOnce) 项目并访问相同的网络资源。此测试失败。

  3. 与(2)相同,但客户端发布并安装在另一台机器上,并使用终端服务器访问它。此测试失败。

为什么第一个测试成功,但第二个和第三个测试失败?如果提供的登录参数并不总是有效,正确的登录参数应该是什么?

您可以使用 ASP.NET 中的内置模拟吗? https://support.microsoft.com/en-ie/help/306158/how-to-implement-impersonation-in-an-asp-net-application

问题是 ReportDocument 没有类似 LoadImpersonate 的东西,所以它总是会尝试使用应用程序池权限打开 .rpt 文件。

你需要的是委托,而不是模拟,如果你使用 windows 身份验证和活动目录,你需要授权你的服务器 and/or 你的应用程序池帐户进行委托...

https://support.microsoft.com/en-us/help/810572/how-to-configure-an-asp-net-application-for-a-delegation-scenario

这样应用程序池帐户将使用用户的权限来访问资源

如果这不可行,作为解决方法,您可以使用模拟将 .rpt 文件复制到您的应用程序池帐户的可访问位置,并在使用后将其删除...