【问题标题】:Connect to network drive with user name and password使用用户名和密码连接到网络驱动器
【发布时间】:2011-04-11 16:20:50
【问题描述】:

如何提供凭据以便我可以连接到 .NET 中的网络驱动器?

我正在尝试从网络驱动器中检索文件,并且需要提供用户凭据才能访问该驱动器。

【问题讨论】:

标签: c# .net


【解决方案1】:

非常优雅的解决方案灵感来自this one。这个只使用 .Net 库,不需要使用任何命令行或 Win32 API。

供参考的代码:

NetworkCredential theNetworkCredential = new NetworkCredential(@"domain\username", "password");
CredentialCache theNetCache = new CredentialCache();
theNetCache.Add(new Uri(@"\\computer"), "Basic", theNetworkCredential);
string[] theFolders = Directory.GetDirectories(@"\\computer\share");

【讨论】:

  • @VladL 您可以使用 Windows 资源管理器手动访问网络共享吗?您对用户有必要的权限吗?
  • 我必须对此进行两次更改才能使其在我的网络上运行。我必须使用具有不同域参数的 NetworkCredential 重载。我不得不从 Basic 切换到 Digest。
  • 我觉得奇怪的是,我们 1) 创建了一个 CredentialsCache 实例,并且 2) 实际上没有将该对象用于任何事情。如果这是某个全球商店(我们所有的操作都会自动命中),我希望会获得一些单身人士。由于我们不是,我认为我们实际上并没有在这里使用凭据来产生任何影响。
  • 我得到了误报。它起作用了,因为我映射了共享。一旦它消失了,我就开始被拒绝异常。
  • 在某些情况下需要指定域。例如域不同的地方。添加到答案中,
【解决方案2】:

最好的方法是 p/invoke WNetUseConnection

[StructLayout(LayoutKind.Sequential)] 
private class NETRESOURCE
{ 
        public int dwScope = 0;
        public int dwType = 0;
        public int dwDisplayType = 0;
        public int dwUsage = 0;
        public string lpLocalName = "";
        public string lpRemoteName = "";
        public string lpComment = "";
        public string lpProvider = "";
}


[DllImport("Mpr.dll")] 
private static extern int WNetUseConnection(
            IntPtr hwndOwner,
            NETRESOURCE lpNetResource,
            string lpPassword,
            string lpUserID,
            int dwFlags,
            string lpAccessName,
            string lpBufferSize,
            string lpResult
        );

Example code here.

【讨论】:

  • 它对我不起作用。连接没有错误,但是访问文件夹时,程序永远卡住了
【解决方案3】:

您可以使用WindowsIdentity 类(带有logon token)在读取和写入文件时进行模拟。

var windowsIdentity = new WindowsIdentity(logonToken);
using (var impersonationContext = windowsIdentity.Impersonate()) {
    // Connect, read, write
}

【讨论】:

  • 仅适用于 Windows 环境。当您开始使用 AS400、Solaris 和 Linux 时,它会变得很麻烦,尤其是当共享需要一个不同于您运行应用程序的凭证时。
  • bzlm 的解决方案有效,但他并没有真正充实它。 Get some code from msdn.microsoft.com/en-us/library/…, namely the safeTokenHandle class and dependencies.
  • 此代码在本地系统上运行,但在具有匿名池标识的 IIS 上无法运行,有什么建议吗?
【解决方案4】:

我真的不知道隐藏的过程,但我使用 webrequest,这样我就能够传递凭据,它对我来说非常有效。

var ftpDownloadFile = WebRequest.Create("filePath");
ftpDownloadFile.Method = WebRequestMethods.Ftp.DownloadFile;
ftpDownloadFile.Credentials = new NetworkCredential("user", "pass");
using (var reader = (FtpWebResponse)ftpDownloadFile.GetResponse())
using (var responseStream = reader.GetResponseStream())
{
    var writeStream = new FileStream(Path.Combine(LocalStorage), FileMode.Create);
    const int length = 2048;
    var buffer = new Byte[length];
    if (responseStream != null)
    {
        var bytesRead = responseStream.Read(buffer, 0, length);
        while (bytesRead > 0)
        {
            writeStream.Write(buffer, 0, bytesRead);
            bytesRead = responseStream.Read(buffer, 0, length);
        }
    }
    reader.Close();
    writeStream.Close();
}

【讨论】:

    【解决方案5】:
    var fileName = "Mylogs.log";
    var local = Path.Combine(@"C:\TempLogs", fileName);
    var remote = Path.Combine(@"\\servername\c$\Windows\Temp\", fileName);
    
    WebClient request = new WebClient();
    request.Credentials = new NetworkCredential(@"username", "password");
    
    if (File.Exists(local))
    {
        File.Delete(local);
    
        File.Copy(remote, local, true);
    }
    else
    {
        File.Copy(remote, local, true);
    }
    

    【讨论】:

      【解决方案6】:

      将此代码用于在 MVC.NET 中测试的模拟,也许对于 dot net core 它需要一些更改,如果你想 dot net core 请告诉我,我会分享。

       public static class ImpersonationAuthenticationNew
          {
              [DllImport("advapi32.dll", SetLastError = true)]
              private static extern bool LogonUser(string usernamee, string domain, string password, LogonType dwLogonType, LogonProvider dwLogonProvider, ref IntPtr phToken);
              [DllImport("kernel32.dll")]
              private static extern bool CloseHandle(IntPtr hObject);
              public static bool Login(string domain,string username, string password)
              {                
                  IntPtr token = IntPtr.Zero;
                  var IsSuccess = LogonUser(username, domain, password, LogonType.LOGON32_LOGON_NEW_CREDENTIALS, LogonProvider.LOGON32_PROVIDER_WINNT50, ref token);
                  if (IsSuccess)
                  {
                      using (WindowsImpersonationContext person = new WindowsIdentity(token).Impersonate())
                      {
                          var xIdentity = WindowsIdentity.GetCurrent();
                          #region Start ImpersonationContext  Scope
                          try
                          {
      
                              // TYPE YOUR CODE HERE 
      
                          }
                          catch (Exception ex) { throw (ex); }
                          finally {
                              person.Undo();
                              CloseHandle(token);
                              return true;
                          }
                          #endregion
                      }
                  }
                  return false;
              }
          }
      
          #region Enums
          public enum LogonType
          {
              /// <summary>
              /// This logon type is intended for users who will be interactively using the computer, such as a user being logged on  
              /// by a terminal server, remote shell, or similar process.
              /// This logon type has the additional expense of caching logon information for disconnected operations;
              /// therefore, it is inappropriate for some client/server applications,
              /// such as a mail server.
              /// </summary>
              LOGON32_LOGON_INTERACTIVE = 2,
      
              /// <summary>
              /// This logon type is intended for high performance servers to authenticate plaintext passwords.
      
              /// The LogonUser function does not cache credentials for this logon type.
              /// </summary>
              LOGON32_LOGON_NETWORK = 3,
      
              /// <summary>
              /// This logon type is intended for batch servers, where processes may be executing on behalf of a user without
              /// their direct intervention. This type is also for higher performance servers that process many plaintext
              /// authentication attempts at a time, such as mail or Web servers.
              /// The LogonUser function does not cache credentials for this logon type.
              /// </summary>
              LOGON32_LOGON_BATCH = 4,
      
              /// <summary>
              /// Indicates a service-type logon. The account provided must have the service privilege enabled.
              /// </summary>
              LOGON32_LOGON_SERVICE = 5,
      
              /// <summary>
              /// This logon type is for GINA DLLs that log on users who will be interactively using the computer.
              /// This logon type can generate a unique audit record that shows when the workstation was unlocked.
              /// </summary>
              LOGON32_LOGON_UNLOCK = 7,
      
              /// <summary>
              /// This logon type preserves the name and password in the authentication package, which allows the server to make
              /// connections to other network servers while impersonating the client. A server can accept plaintext credentials
              /// from a client, call LogonUser, verify that the user can access the system across the network, and still
              /// communicate with other servers.
              /// NOTE: Windows NT:  This value is not supported.
              /// </summary>
              LOGON32_LOGON_NETWORK_CLEARTEXT = 8,
      
              /// <summary>
              /// This logon type allows the caller to clone its current token and specify new credentials for outbound connections.
              /// The new logon session has the same local identifier but uses different credentials for other network connections.
              /// NOTE: This logon type is supported only by the LOGON32_PROVIDER_WINNT50 logon provider.
              /// NOTE: Windows NT:  This value is not supported.
              /// </summary>
              LOGON32_LOGON_NEW_CREDENTIALS = 9,
          }
          public enum LogonProvider
          {
              /// <summary>
              /// Use the standard logon provider for the system.
              /// The default security provider is negotiate, unless you pass NULL for the domain name and the user name
              /// is not in UPN format. In this case, the default provider is NTLM.
              /// NOTE: Windows 2000/NT:   The default security provider is NTLM.
              /// </summary>
              LOGON32_PROVIDER_DEFAULT = 0,
              LOGON32_PROVIDER_WINNT35 = 1,
              LOGON32_PROVIDER_WINNT40 = 2,
              LOGON32_PROVIDER_WINNT50 = 3
          }
          #endregion
      

      【讨论】:

        【解决方案7】:

        将此代码用于在 MVC.NET 中测试的模拟,也许对于 dot net core 它需要一些更改,如果你想 dot net core 请告诉我,我会分享。

         public static class ImpersonationAuthenticationNew
            {
                [DllImport("advapi32.dll", SetLastError = true)]
                private static extern bool LogonUser(string usernamee, string domain, string password, LogonType dwLogonType, LogonProvider dwLogonProvider, ref IntPtr phToken);
                [DllImport("kernel32.dll")]
                private static extern bool CloseHandle(IntPtr hObject);
                public static bool Login(string domain,string username, string password)
                {                
                    IntPtr token = IntPtr.Zero;
                    var IsSuccess = LogonUser(username, domain, password, LogonType.LOGON32_LOGON_NEW_CREDENTIALS, LogonProvider.LOGON32_PROVIDER_WINNT50, ref token);
                    if (IsSuccess)
                    {
                        using (WindowsImpersonationContext person = new WindowsIdentity(token).Impersonate())
                        {
                            var xIdentity = WindowsIdentity.GetCurrent();
                            #region Start ImpersonationContext  Scope
                            try
                            {
        
                                // TYPE YOUR CODE HERE 
                              return true;
                            }
                            catch (Exception ex) { throw (ex); }
                            finally {
                                person.Undo();
                                CloseHandle(token);
                               
                            }
                            #endregion
                        }
                    }
                    return false;
                }
            }
        
            #region Enums
            public enum LogonType
            {
                /// <summary>
                /// This logon type is intended for users who will be interactively using the computer, such as a user being logged on  
                /// by a terminal server, remote shell, or similar process.
                /// This logon type has the additional expense of caching logon information for disconnected operations;
                /// therefore, it is inappropriate for some client/server applications,
                /// such as a mail server.
                /// </summary>
                LOGON32_LOGON_INTERACTIVE = 2,
        
                /// <summary>
                /// This logon type is intended for high performance servers to authenticate plaintext passwords.
        
                /// The LogonUser function does not cache credentials for this logon type.
                /// </summary>
                LOGON32_LOGON_NETWORK = 3,
        
                /// <summary>
                /// This logon type is intended for batch servers, where processes may be executing on behalf of a user without
                /// their direct intervention. This type is also for higher performance servers that process many plaintext
                /// authentication attempts at a time, such as mail or Web servers.
                /// The LogonUser function does not cache credentials for this logon type.
                /// </summary>
                LOGON32_LOGON_BATCH = 4,
        
                /// <summary>
                /// Indicates a service-type logon. The account provided must have the service privilege enabled.
                /// </summary>
                LOGON32_LOGON_SERVICE = 5,
        
                /// <summary>
                /// This logon type is for GINA DLLs that log on users who will be interactively using the computer.
                /// This logon type can generate a unique audit record that shows when the workstation was unlocked.
                /// </summary>
                LOGON32_LOGON_UNLOCK = 7,
        
                /// <summary>
                /// This logon type preserves the name and password in the authentication package, which allows the server to make
                /// connections to other network servers while impersonating the client. A server can accept plaintext credentials
                /// from a client, call LogonUser, verify that the user can access the system across the network, and still
                /// communicate with other servers.
                /// NOTE: Windows NT:  This value is not supported.
                /// </summary>
                LOGON32_LOGON_NETWORK_CLEARTEXT = 8,
        
                /// <summary>
                /// This logon type allows the caller to clone its current token and specify new credentials for outbound connections.
                /// The new logon session has the same local identifier but uses different credentials for other network connections.
                /// NOTE: This logon type is supported only by the LOGON32_PROVIDER_WINNT50 logon provider.
                /// NOTE: Windows NT:  This value is not supported.
                /// </summary>
                LOGON32_LOGON_NEW_CREDENTIALS = 9,
            }
            public enum LogonProvider
            {
                /// <summary>
                /// Use the standard logon provider for the system.
                /// The default security provider is negotiate, unless you pass NULL for the domain name and the user name
                /// is not in UPN format. In this case, the default provider is NTLM.
                /// NOTE: Windows 2000/NT:   The default security provider is NTLM.
                /// </summary>
                LOGON32_PROVIDER_DEFAULT = 0,
                LOGON32_PROVIDER_WINNT35 = 1,
                LOGON32_PROVIDER_WINNT40 = 2,
                LOGON32_PROVIDER_WINNT50 = 3
            }
            #endregion
        

        【讨论】:

          【解决方案8】:

          您可以使用 system.diagnostocs.process 调用“net use .... with userid and password”或使用这些命令的 shell。

          【讨论】:

          • 你可以,但你愿意吗?
          • 如果它实现了您的用例的目标,那为什么不呢,那么它是完全有效的。它的一行代码可以达到预期的结果。它内置了所有错误处理功能,并且经过了测试。重写功能似乎很愚蠢。
          • “如果它达到了你的用例的目标,那么它是完全有效的”——这是一个非常笼统的说法,你的回答在我看来是一个反例。启动一个新流程来做一些可以在单个 P/Invoke 中完成的事情(不需要重写)是使用大锤来破解。
          【解决方案9】:

          您可以使用 WebClient 类使用凭据连接到网络驱动程序。包括以下命名空间:

          using System.Net;
          
          WebClient request = new WebClient();
          request.Credentials = new NetworkCredential("domain\username", "password");
          string[] theFolders = Directory.GetDirectories(@"\\computer\share");
          

          【讨论】:

          • Directory.GetDirectories 与 WebClient 无关 - 它们恰好是您示例中的相邻代码行
          猜你喜欢
          • 1970-01-01
          • 2018-09-20
          • 2014-12-31
          • 1970-01-01
          • 2010-12-04
          • 2021-09-22
          • 2011-03-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多