使用用户名和密码连接到网络驱动器
Posted
技术标签:
【中文标题】使用用户名和密码连接到网络驱动器【英文标题】:Connect to network drive with user name and password 【发布时间】:2011-04-11 16:20:50 【问题描述】:如何提供凭据以便我可以连接到 .NET 中的网络驱动器?
我正在尝试从网络驱动器中检索文件,并且需要提供用户凭据才能访问该驱动器。
【问题讨论】:
我相信还有更通用的方式:***.com/questions/295538/… 【参考方案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 无关 - 它们恰好是您示例中的相邻代码行以上是关于使用用户名和密码连接到网络驱动器的主要内容,如果未能解决你的问题,请参考以下文章
如何使用映射的网络驱动器通过数据源 (ODBC) 连接到 Access 数据库?
ODBC 从 R 连接到网络驱动器上的 Access DB .accdb 文件