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

C# 如何使用模拟从IIS访问网络资源?,c#,asp.net-web-api,crystal-reports,asp.net-web-api2,C#,Asp.net Web Api,Crystal Reports,Asp.net Web Api2,我有一个WebApi应用程序,需要访问不同机器上的网络共享并打开Crystal Reports文件 我正在使用LogonUser和WindowsIdentity.Impersonate模拟使用此代码拥有网络共享权限的用户(不完整): 例如,当使用托管代码(System.IO)列出文件夹或删除文件时,这种方法可以很好地工作。但是,我需要打开Crystal Reports文件(我有最新版本),这样做时,我会遇到一个异常: 拒绝访问 我假设CR试图在应用程序池用户的上下文中加载文件 如果我将应用程序池

我有一个WebApi应用程序,需要访问不同机器上的网络共享并打开Crystal Reports文件

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

例如,当使用托管代码(
System.IO
)列出文件夹或删除文件时,这种方法可以很好地工作。但是,我需要打开Crystal Reports文件(我有最新版本),这样做时,我会遇到一个异常:

拒绝访问

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

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

将为.NET4.6帮助使用新的
WindowsIdentity.RunImpersonated
,或者它将产生相同的结果。如果是,是否有办法让CR在提供的用户上下文中而不是在应用程序池/AppDomain用户中运行

更新

通过将
LogonUser
参数更改为
LOGON32\u LOGON\u NEW\u凭据
LOGON32\u PROVIDER\u WINNT50
,我取得了部分成功。然后我测试了以下内容:

  • 从VS2017本地启动项目(以便WebApi项目在本地IIS Express上下文中运行),并使用我的计算机上的客户端应用程序访问网络资源。这次试验是成功的

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

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


  • 为什么第一次测试成功,但测试2和3失败?如果提供的登录参数不能始终正常工作,那么正确的登录参数应该是什么?

    您可以在ASP.NET中使用内置模拟吗?。
    您是否可以在ASP.NET中使用内置模拟?。
    问题在于ReportDocument没有类似LoadImpersonate的功能,因此,它将始终尝试使用应用程序池权限打开.rpt文件

    您需要的是委派,而不是模拟,如果您使用windows身份验证和active directory,则需要授权您的服务器和/或应用程序池帐户进行委派

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


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

    问题是ReportDocument没有类似LoadImpersonate的功能,因此,它将始终尝试使用应用程序池权限打开.rpt文件

    您需要的是委派,而不是模拟,如果您使用windows身份验证和active directory,则需要授权您的服务器和/或应用程序池帐户进行委派

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


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

    如果您可以使用远程文件,则听起来模拟很有效。但你所说的“打开Crystal Reports文件”是什么意思,与在共享上打开文件不同吗?可能Crystal Reports不支持此功能。您是否尝试将共享文件夹映射为驱动器?@SimonMourier我的意思是将.rpt文件加载到文档中,设置参数并打印报告。这与从共享打开有何区别?如果您可以使用远程文件,则听起来像是模拟工作。但你所说的“打开Crystal Reports文件”是什么意思,与在共享上打开文件不同吗?可能Crystal Reports不支持此功能。您是否尝试将共享文件夹映射为驱动器?@SimonMourier我的意思是将.rpt文件加载到文档中,设置参数并打印报告。这与从共享打开有何区别?
    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();
    }