【问题标题】:Downloading a file from a Remote File share throws access denied从远程文件共享下载文件会导致访问被拒绝
【发布时间】:2018-03-17 12:57:57
【问题描述】:

我在 ASP.Net 通用处理程序中有以下代码来下载文件。

// generate you file
// set FilePath and FileName variables
string stFile = FilePath + FileName;
try {
    response.Clear();
    response.ContentType = "application/pdf";
    response.AppendHeader("Content-Disposition", "attachment; filename=" + FileName + ";");
    response.TransmitFile(stFile);
} catch (Exception ex) {
    // any error handling mechanism
} finally {
    response.End();
}

它适用于本地路径 - 例如“D:\Files\Sample.pdf”或“\localserver\Files\Sample.pdf”。

但它在尝试访问“\anotherServer\Files\Sample.pdf”等网络文件共享时抛出并拒绝访问错误。

它与双跳有关吗?如果我可以使用 spsecurity.runwithelevatedprivileges 来解决这个问题?或者其他选项是什么?

根据这篇文章https://weblogs.asp.net/owscott/iis-windows-authentication-and-the-double-hop-issue,这似乎是一个双跳问题。我该如何解决这个问题?我想要的是最终用户应该能够使用 asp.net 通用处理程序下载远程资源。

【问题讨论】:

  • 应用程序池的标识(通常取决于您的站点配置)是尝试访问该共享的标识。什么是应用程序池标识,它是否具有读取权限?
  • 是的,应用程序池拥有完全控制权。
  • 共享文件的权限设置在两个地方——共享权限和文件的“经典”权限。我经常陷入忘记其中一个地方的陷阱;)你检查过这两个地方吗?
  • 不是一个真正的答案,但也许您可以通过模拟 (support.microsoft.com/en-us/help/306158/…) 解决此限制?只是为了测试,看看它是否有效(可能与应用程序池相同的用户)
  • @AlexandruClonțea,我能够通过使用 SPSecurity.RunWithElevatedPrivileges(delegate () {context.Response.TransmitFile(string.Format(@"{0}\{1}", mediaCenterImageFolder , 文件名));});如果我遇到任何问题,我会尝试冒充。

标签: c# asp.net sharepoint httpresponse ashx


【解决方案1】:

我必须处理一次类似的事情,并通过将网络共享映射到特定驱动器来使其正常工作。

在尝试访问之前将凭据添加到您的网络共享的解决方案不起作用(但您可以尝试作为第一次尝试)

NetworkCredential nc = new NetworkCredential("<login>", "<pass>");
CredentialCache cache = new CredentialCache();
cache.Add(new Uri("<your network share>"), "Basic", nc);

如果这不起作用,请使用将网络共享映射到驱动器的组合解决方案。使用类NetworkDriveWNetAddConnection2WNetCancelConnection2 进行WinApi 调用:

public class NetworkDrive
{
    public enum ResourceScope
    {
        RESOURCE_CONNECTED = 1,
        RESOURCE_GLOBALNET,
        RESOURCE_REMEMBERED,
        RESOURCE_RECENT,
        RESOURCE_CONTEXT
    }

    public enum ResourceType
    {
        RESOURCETYPE_ANY,
        RESOURCETYPE_DISK,
        RESOURCETYPE_PRINT,
        RESOURCETYPE_RESERVED
    }

    public enum ResourceUsage
    {
        RESOURCEUSAGE_CONNECTABLE = 0x00000001,
        RESOURCEUSAGE_CONTAINER = 0x00000002,
        RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004,
        RESOURCEUSAGE_SIBLING = 0x00000008,
        RESOURCEUSAGE_ATTACHED = 0x00000010,
        RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED),
    }

    public enum ResourceDisplayType
    {
        RESOURCEDISPLAYTYPE_GENERIC,
        RESOURCEDISPLAYTYPE_DOMAIN,
        RESOURCEDISPLAYTYPE_SERVER,
        RESOURCEDISPLAYTYPE_SHARE,
        RESOURCEDISPLAYTYPE_FILE,
        RESOURCEDISPLAYTYPE_GROUP,
        RESOURCEDISPLAYTYPE_NETWORK,
        RESOURCEDISPLAYTYPE_ROOT,
        RESOURCEDISPLAYTYPE_SHAREADMIN,
        RESOURCEDISPLAYTYPE_DIRECTORY,
        RESOURCEDISPLAYTYPE_TREE,
        RESOURCEDISPLAYTYPE_NDSCONTAINER
    }

    [StructLayout(LayoutKind.Sequential)]
    private class NETRESOURCE
    {
        public ResourceScope dwScope = 0;
        public ResourceType dwType = 0;
        public ResourceDisplayType dwDisplayType = 0;
        public ResourceUsage dwUsage = 0;
        public string lpLocalName = null;
        public string lpRemoteName = null;
        public string lpComment = null;
        public string lpProvider = null;
    }

    [DllImport("mpr.dll")]
    private static extern int WNetAddConnection2(NETRESOURCE lpNetResource, string lpPassword, string lpUsername, int dwFlags);

    [DllImport("mpr.dll")]
    static extern int WNetCancelConnection2(string lpName, Int32 dwFlags, bool bForce);

    private const int CONNECT_UPDATE_PROFILE = 0x1;
    private const int NO_ERROR = 0;

    public int MapNetworkDrive(string unc, string drive, string user, string password)
    {
        NETRESOURCE myNetResource = new NETRESOURCE();
        myNetResource.lpLocalName = drive;
        myNetResource.lpRemoteName = unc;
        myNetResource.lpProvider = null;
        int result = WNetAddConnection2(myNetResource, password, user, 0);
        if (result == 0)
            return result;
        else
            throw new Win32Exception(Marshal.GetLastWin32Error());
    }

    public int UnmapNetworkDrive(string drive)
    {
        int result = WNetCancelConnection2(drive, CONNECT_UPDATE_PROFILE, true);
        if (result != NO_ERROR)
        {
            throw new Win32Exception(Marshal.GetLastWin32Error());
        }
        return result;
    }
}

并像这样使用它:

NetworkDrive nd = new NetworkDrive();

try
{
    if (nd.MapNetworkDrive("<your network share>", "Z:", "<login>", "<pass>") == 0)
    {
        NetworkCredential nc = new NetworkCredential("<login>", "<pass>");
        CredentialCache cache = new CredentialCache();
        cache.Add(new Uri("<your network share>"), "Basic", nc);

        // access network share using UNC path (not your drive letter)
    }
}
finally
{
    nd.UnmapNetworkDrive("Z:");
}

【讨论】:

  • 谢谢你,@tinamou。不知何故,我能够通过使用 SPSecurity.RunWithElevatedPrivileges(delegate () {context.Response.TransmitFile(string.Format(@"{0}\{1}", mediaCenterImageFolder, fileName));});跨度>
  • 很高兴听到这个消息:)
【解决方案2】:

您需要提供文件权限,一旦您的工作完成,您需要撤销它们。 最好在 finally 块中使用 try finally 块,您可以撤销权限

有关文件权限的示例,您可以在 MSDN Link 中找到

文件名不应包含空格,因为它会损坏 mozilla 浏览器中的下载

【讨论】:

  • 每个人都被授予经典文件夹级别权限和共享权限。
【解决方案3】:

我之前也遇到过同样的问题,你的代码对我来说很好,你需要检查的是安全性和文件权限。

假设您的处理程序托管在 IIS 下,您的应用程序池标识必须设置为域用户,才能使用该用户的权限运行 IIS 进程。

因此您必须授予该用户读取/写入共享文件夹内容的权限。

我通常这样做是为了访问简单应用程序的数据库和 SAN 存储。

【讨论】:

  • 如前所述,包括应用程序池帐户在内的每个人都被授予经典文件夹级别权限和共享权限。
【解决方案4】:

如果您使用默认生成的 IIS 应用程序池标识,您的工作进程将尝试以域注册计算机帐户的身份访问网络资源(例如:yourdomain\machinename$)。有关 IIS 在这些情况下如何运行的更多详细信息,请参阅 here

只要您尝试访问的服务器在同一个域中,您只需设置“共享”权限和 NTFS 权限(在共享文件夹的安全性下)以允许该域计算机帐户访问股份。

注意:在安全对话框中选择帐户时,默认情况下不会列出机器帐户 - 您需要在“选择用户和组”对话框中单击“对象类型”并添加“计算机”。有关 IIS 在这些情况下如何运行的更多详细信息,请参阅here

【讨论】:

    【解决方案5】:

    就我而言,它(最终)在下载过程中添加了这一行:
    Response.AddHeader("Transfer-Encoding", "identity"); 在我的网络应用程序中,我也这样做了:

    • 我使用 UNC 路径下载文件
    • 我模拟了 Web 应用程序在我的用户下工作,我是管理员
    • 我还为我的用户设置了应用程序池

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-28
      • 1970-01-01
      • 2022-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-26
      • 2023-02-10
      相关资源
      最近更新 更多