【问题标题】:.NET Impersonate and file upload issues.NET 模拟和文件上传问题
【发布时间】:2011-02-02 14:24:13
【问题描述】:

我有一个网页,允许用户将文件上传到网络共享。当我在本地(在 VS 2008 中)运行网页并尝试上传文件时,它可以工作!但是,当我将网站部署到网络服务器并尝试通过网页上传文件时,它不起作用

在网络服务器上返回给我的错误说“访问路径 '\05prd1\emp\test.txt' 被拒绝。所以,很明显,这是一个权限问题。

网络共享配置为允许对我(NT 身份验证)和网络服务(这是 .NET 的默认帐户以及我们在 IIS 应用程序池中设置为该网站的默认用户的帐户)进行完全访问。

我在网络服务器上尝试过模拟和不模拟,但两种方法都不起作用,但两种方法都可以在我的本地机器上工作(换句话说,无论有没有模拟都可以在我的本地机器上工作)。

上传文件的代码如下。请注意,下面的代码包括模拟,但就像我上面所说的,我尝试过模拟和不模拟,但没有任何区别。

if (fuCourses.PostedFile != null && fuCourses.PostedFile.ContentLength > 0) {
    System.Security.Principal.WindowsImpersonationContext impCtx;
    impCtx =
        ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();

    try {
        lblMsg.Visible = true;

        // The courses file to be uploaded
        HttpPostedFile file = fuCourses.PostedFile;
        string fName = file.FileName;
        string uploadPath = "\\\\05prd1\\emp\\";

        // Get the file name
        if (fName.Contains("\\")) {
            fName = fName.Substring(
                fName.LastIndexOf("\\") + 1);
        }

        // Delete the courses file if it is already on \\05prd1\emp
        FileInfo fi = new FileInfo(uploadPath + fName);
        if (fi != null && fi.Exists) {
            fi.Delete();
        }

        // Open new file stream on \\05prd1\emp and read bytes into it from file upload
        FileStream fs = File.Create(uploadPath + fName, file.ContentLength);

        using (Stream stream = file.InputStream) {
            byte[] b = new byte[4096];
            int read;

            while ((read = stream.Read(b, 0, b.Length)) > 0) {
                fs.Write(b, 0, read);
            }
        }

        fs.Close();

        lblMsg.Text = "File Successfully Uploaded";
        lblMsg.ForeColor = System.Drawing.Color.Green;
    }
    catch (Exception ex) {
        lblMsg.Text = ex.Message;
        lblMsg.ForeColor = System.Drawing.Color.Red;
    }
    finally {
        impCtx.Undo();
    }
}

对此的任何帮助将不胜感激!

【问题讨论】:

  • 我没有太多有用的补充,除了我已经尝试过多次这样做。我从来没有设法让 IIS 处理从 ASP.Net 应用程序对网络共享的访问。不过,它会在开发服务器中正常工作。
  • 您使用什么来在网络服务器上托管网站? IIS6 或 IIS7 还是别的什么?您是否尝试过在 IIS 上本地运行您的网站?
  • 是的,我同意你的观点。这不是我第一次尝试解决这个问题。过去,我不得不做一些愚蠢的事情,比如将二进制文件写入数据库,然后从数据库中读取存储过程并将其重写到磁盘上的文件中。但是,我知道这样做是可能的,因为我使用了一些 Telerik 控件,这些控件允许人们在某些文本中嵌入图像文件,最终 Telerik 控件所做的是将图像文件写入预定义的网络分享。
  • @David - 抱歉,我错过了你的最后一个问题。不,我没有尝试在本地 IIS 上运行它。我会假设行为与网络服务器上的行为相同。但即使它成功了,我也不确定那会证明给我什么。有什么想法吗?
  • 哇...看来我把所有人都难住了。

标签: .net file-upload impersonation


【解决方案1】:

问题在于 Kerberos 没有从网络服务器委托给文件服务器。理想的解决方案是将 Kerberos 委托给文件服务器。不幸的是,这不是我有能力改变的。太多的繁文缛节和太多的政治。但是,我想出了一些技巧。

我创建了一个位于网站根目录的临时文件夹。使用模拟,我将文件写入这个临时文件夹(换句话说,它被上传到这个临时文件夹)。

将文件写入临时文件夹后,我将文件复制到文件服务器 UNC。这是第二跳,无论我是否使用模拟,这都没有区别——因为发送到文件服务器的凭据是网络服务器本身的凭据。因此,这迫使我做的是授予对 UNC 共享上的网络服务器的读/写访问权限。完成所有这些操作后,文件副本按预期工作。

【讨论】:

    【解决方案2】:

    您没有提及您在 IIS 中使用哪种身份验证。

    如果您依赖 Windows 集成/NTLM 身份验证,那么我认为您会遇到一个问题,除非您可以在服务器上配置 Kerberos,否则用户的身份验证令牌无法在当前(Web)服务器之外使用 - “double-hop”的问题。

    如果您使用 Basic(在 IIS 中)或 Forms(通过 ASP.NET),那么您将可以访问明文形式的用户密码。然后,您可以使用用户名/密码调用模拟代码,并且应该能够以该用户身份访问共享文件夹。

    我也很确定,如果您使用基本身份验证,那么 标记将适用于网络共享访问。

    查看 KB 306158 了解更多信息和代码示例。

    【讨论】:

    • 是的,我们的域使用 NTLM 进行身份验证,在我的网站中,我也使用 Windows 身份验证。我尝试使用编程模拟来验证文件服务器上的用户(在第二跳),但它不起作用。我可以通过访问文件服务器上的安全日志来验证这一点。安全日志显示请求来自网络服务器,并且它尝试使用网络服务器进行身份验证,而不是被模拟的用户。
    • 澄清一下,模拟在第二跳不起作用。它适用于网络服务器,但之后它被击落。我相信这是因为,正如我们之前所说,Kerberos 没有被正确委派(这是我无法控制的)。
    • 没错。如果你被 NTLM 卡住了,那么第二跳会咬你。
    猜你喜欢
    • 1970-01-01
    • 2019-10-29
    • 2012-12-26
    • 2021-03-31
    • 2021-08-05
    • 2014-03-21
    • 2011-11-12
    • 1970-01-01
    • 2010-10-17
    相关资源
    最近更新 更多