如何使用模拟从 IIS 访问网络资源?
How to use impersonation to access a network resource from IIS?
我有一个 WebApi 应用需要访问另一台机器上的网络共享并打开 Crystal 报告文件。
我正在使用 LogonUser
和 WindowsIdentity.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_CREDENTIALS
和 LOGON32_PROVIDER_WINNT50
取得了部分成功。然后我测试了以下内容:
从 VS2017 本地启动项目(以便 WebApi 项目 运行s 在本地 IIS Express 上下文中)并使用我机器上的客户端应用程序访问网络资源。这次测试成功了。
在单独的机器上发布了 IIS 上的 WebApi 项目。在我的机器上启动客户端 (ClickOnce) 项目并访问相同的网络资源。此测试失败。
与(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 你的应用程序池帐户进行委托...
这样应用程序池帐户将使用用户的权限来访问资源
如果这不可行,作为解决方法,您可以使用模拟将 .rpt 文件复制到您的应用程序池帐户的可访问位置,并在使用后将其删除...
我有一个 WebApi 应用需要访问另一台机器上的网络共享并打开 Crystal 报告文件。
我正在使用 LogonUser
和 WindowsIdentity.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_CREDENTIALS
和 LOGON32_PROVIDER_WINNT50
取得了部分成功。然后我测试了以下内容:
从 VS2017 本地启动项目(以便 WebApi 项目 运行s 在本地 IIS Express 上下文中)并使用我机器上的客户端应用程序访问网络资源。这次测试成功了。
在单独的机器上发布了 IIS 上的 WebApi 项目。在我的机器上启动客户端 (ClickOnce) 项目并访问相同的网络资源。此测试失败。
与(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 你的应用程序池帐户进行委托...
这样应用程序池帐户将使用用户的权限来访问资源
如果这不可行,作为解决方法,您可以使用模拟将 .rpt 文件复制到您的应用程序池帐户的可访问位置,并在使用后将其删除...