【问题标题】:Copy file on a network shared drive复制网络共享驱动器上的文件
【发布时间】:2020-03-20 18:48:50
【问题描述】:

我有一个网络共享驱动器(“\serverur\folder”),我想在其上复制文件。 我可以使用特定用户(“用户”/“通行证”)在驱动器上写入。 如何使用 C# 访问具有写入权限的共享驱动器?

【问题讨论】:

    标签: c# authentication network-drive


    【解决方案1】:

    未经测试的代码,但类似于:

    AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
    
    // http://pinvoke.net/default.aspx/advapi32/LogonUser.html    
    IntPtr token;
    LogonUser("username", "domain", "password", LogonType.LOGON32_LOGON_BATCH, LogonProvider.LOGON32_PROVIDER_DEFAULT);
    
    WindowsIdentity identity = new WindowsIdentity(token);
    
    WindowsImpersonationContext context = identity.Impersonate();
    
    try
    {
        File.Copy(@"c:\temp\MyFile.txt", @"\\server\folder\Myfile.txt", true);
    }
    finally
    {
        context.Undo();
    }
    

    【讨论】:

    【解决方案2】:

    这是一个适用于 ASP.NET 应用程序的工作示例。 Original source

    private void SendToFileShare(byte[] pdfData, string fileName)
    {
        if(pdfData == null)
        {
            throw new ArgumentNullException("pdfData");
        }
        if (string.IsNullOrWhiteSpace(fileName))
        {
            //Assign a unique name because the programmer failed to specify one.
            fileName = Guid.NewGuid().ToString();
        }
        else
        {
            //Should probably replace special characters (windows filenames) with something.                
        }
    
    
        string networkShareLocation = @"\\your\network\share\";
    
        var path = $"{networkShareLocation}{fileName}.pdf";
    
    
        //Credentials for the account that has write-access. Probably best to store these in a web.config file.
        var domain = "AB";
        var userID = "Mr";
        var password = "C";
    
    
        if (ImpersonateUser(domain, userID, password) == true)
        {
            //write the PDF to the share:
            System.IO.File.WriteAllBytes(path, report);
    
            undoImpersonation();
        }
        else
        {
            //Could not authenticate account. Something is up.
            //Log or something.
        }
    }
    
    /// <summary>
    /// Impersonates the given user during the session.
    /// </summary>
    /// <param name="domain">The domain.</param>
    /// <param name="userName">Name of the user.</param>
    /// <param name="password">The password.</param>
    /// <returns></returns>
    private bool ImpersonateUser(string domain, string userName, string password)
    {
        WindowsIdentity tempWindowsIdentity;
        IntPtr token = IntPtr.Zero;
        IntPtr tokenDuplicate = IntPtr.Zero;
    
        if (RevertToSelf())
        {
            if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
                LOGON32_PROVIDER_DEFAULT, ref token) != 0)
            {
                if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                {
                    tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                    impersonationContext = tempWindowsIdentity.Impersonate();
                    if (impersonationContext != null)
                    {
                        CloseHandle(token);
                        CloseHandle(tokenDuplicate);
                        return true;
                    }
                }
            }
        }
        if (token != IntPtr.Zero)
            CloseHandle(token);
        if (tokenDuplicate != IntPtr.Zero)
            CloseHandle(tokenDuplicate);
        return false;
    }
    
    /// <summary>
    /// Undoes the current impersonation.
    /// </summary>
    private void undoImpersonation()
    {
        impersonationContext.Undo();
    }
    
    
    #region Impersionation global variables
    public const int LOGON32_LOGON_INTERACTIVE = 2;
    public const int LOGON32_PROVIDER_DEFAULT = 0;
    
    WindowsImpersonationContext impersonationContext;
    
    [DllImport("advapi32.dll")]
    public static extern int LogonUserA(String lpszUserName,
        String lpszDomain,
        String lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        ref IntPtr phToken);
    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int DuplicateToken(IntPtr hToken,
        int impersonationLevel,
        ref IntPtr hNewToken);
    
    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool RevertToSelf();
    
    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern bool CloseHandle(IntPtr handle);
    #endregion
    

    【讨论】:

    • 为什么要复制令牌?
    【解决方案3】:

    更简单和现代的方法。在企业网络中为我工作。

     try
    {
        bool validLogin = false;
        using (PrincipalContext tempcontext = new PrincipalContext(ContextType.Domain, "domain.company.com", null, ContextOptions.Negotiate))
        {
            try
            {
                validLogin = tempcontext.ValidateCredentials("USERNAME", "PASSWORD", ContextOptions.Negotiate);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        if (validLogin)
        {
            File.Copy(@"C:\folder\filename.txt", @"\\domain\folder\filename.txt", true);
            return true;
        }
        else
        {
            MessageBox.Show("Username or Password is incorrect...", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            return false;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        return false;
    }
    

    【讨论】:

      【解决方案4】:

      创建一个具有写入网络驱动器权限的用户,并在 c# 中使用模拟来在访问驱动器时使用该用户。

      【讨论】:

        猜你喜欢
        • 2019-12-26
        • 2013-01-23
        • 1970-01-01
        • 1970-01-01
        • 2021-11-05
        • 1970-01-01
        • 2011-04-21
        • 2017-10-14
        • 1970-01-01
        相关资源
        最近更新 更多