代码之家  ›  专栏  ›  技术社区  ›  Jagd Dai

.NET模拟和文件上载问题

  •  3
  • Jagd Dai  · 技术社区  · 16 年前

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

    在Web服务器上返回给我的错误表示“拒绝访问路径\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();
        }
    }
    

    如有任何帮助,我们将不胜感激!

    2 回复  |  直到 16 年前
        1
  •  1
  •   David Gardiner    16 年前

    您没有提到您在IIS中使用的身份验证类型。

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

    如果使用基本(在IIS中)或表单(通过ASP.NET),则可以以明文形式访问用户的密码。然后,您可以使用用户名/密码调用模拟代码,并且应该能够作为该用户访问共享文件夹。

    我也很确定,如果您使用基本身份验证,那么<identity impersonate=“true”>标记将用于网络共享访问。

    退房KB 306158 更多信息和代码示例。

        2
  •  1
  •   Jagd Dai    16 年前

    存在的问题是,没有将Kerberos从Web服务器委托给文件服务器。理想的解决方案是将Kerberos委托给文件服务器。不幸的是,这不是我有能力改变的。太多的繁文缛节和太多的政治。不过,我想出了一个类似的方法。

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

    把文件写到temp文件夹之后,我就 复制 文件到文件服务器UNC。这是第二个跃点,在这里,无论我是否使用模拟都没有任何区别——因为发送到文件服务器的凭据是Web服务器本身的凭据。所以,这迫使我做的是在UNC共享上授予对Web服务器的读/写访问权。在完成所有这些操作之后,文件拷贝工作正常。