在 C# 中访问 Windows 中受密码保护的网络驱动器?
Posted
技术标签:
【中文标题】在 C# 中访问 Windows 中受密码保护的网络驱动器?【英文标题】:Accessing Password Protected Network Drives in Windows in C#? 【发布时间】:2011-02-03 13:23:20 【问题描述】:所以在 C# 中,我试图访问网络上的文件,例如“//applications/myapp/test.txt”,如下所示:
const string fileLocation = @"//applications/myapp/test.txt";
using (StreamReader fin = new StreamReader(FileLocation))
while(!fin.EndOfStream())
//Do some cool stuff with file
但是我收到以下错误:
System.IO.IOException : Logon failure: unknown user name or bad password.
我认为这是因为我需要提供一些网络凭据,但我不确定如何让这些凭据在这种情况下工作。
有没有人知道最好的方式(或任何方式)来访问这些受密码保护的位置上的文件?
提前致谢!!
【问题讨论】:
this question 的重复? 【参考方案1】:这是我修改代码的方式:
using System;
using System.Runtime.InteropServices;
/// <summary>
/// Implements P/Invoke Interop calls to the operating system.
/// </summary>
internal static class NativeMethods
/// <summary>
/// The type of logon operation to perform.
/// </summary>
internal enum LogonType : int
/// <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>
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>
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>
Batch = 4,
/// <summary>
/// Indicates a service-type logon. The account provided must have
/// the service privilege enabled.
/// </summary>
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>
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>
NetworkCleartext = 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>
NewCredentials = 9
/// <summary>
/// Specifies the logon provider.
/// </summary>
internal enum LogonProvider : int
/// <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>
Default = 0,
/// <summary>
/// Use this provider if you'll be authenticating against a Windows
/// NT 3.51 domain controller (uses the NT 3.51 logon provider).
/// </summary>
WinNT35 = 1,
/// <summary>
/// Use the NTLM logon provider.
/// </summary>
WinNT40 = 2,
/// <summary>
/// Use the negotiate logon provider.
/// </summary>
WinNT50 = 3
/// <summary>
/// The type of logon operation to perform.
/// </summary>
internal enum SecurityImpersonationLevel : int
/// <summary>
/// The server process cannot obtain identification information
/// about the client, and it cannot impersonate the client. It is
/// defined with no value given, and thus, by ANSI C rules,
/// defaults to a value of zero.
/// </summary>
Anonymous = 0,
/// <summary>
/// The server process can obtain information about the client,
/// such as security identifiers and privileges, but it cannot
/// impersonate the client. This is useful for servers that export
/// their own objects, for example, database products that export
/// tables and views. Using the retrieved client-security
/// information, the server can make access-validation decisions
/// without being able to use other services that are using the
/// client's security context.
/// </summary>
Identification = 1,
/// <summary>
/// The server process can impersonate the client's security
/// context on its local system. The server cannot impersonate the
/// client on remote systems.
/// </summary>
Impersonation = 2,
/// <summary>
/// The server process can impersonate the client's security
/// context on remote systems.
/// NOTE: Windows NT: This impersonation level is not supported.
/// </summary>
Delegation = 3
/// <summary>
/// Logs on the user.
/// </summary>
/// <param name="userName">Name of the user.</param>
/// <param name="domain">The domain.</param>
/// <param name="password">The password.</param>
/// <param name="logonType">Type of the logon.</param>
/// <param name="logonProvider">The logon provider.</param>
/// <param name="token">The token.</param>
/// <returns>True if the function succeeds, false if the function fails.
/// To get extended error information, call GetLastError.</returns>
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool LogonUser(
string userName,
string domain,
string password,
LogonType logonType,
LogonProvider logonProvider,
out IntPtr token);
/// <summary>
/// Duplicates the token.
/// </summary>
/// <param name="existingTokenHandle">The existing token
/// handle.</param>
/// <param name="securityImpersonationLevel">The security impersonation
/// level.</param>
/// <param name="duplicateTokenHandle">The duplicate token
/// handle.</param>
/// <returns>True if the function succeeds, false if the function fails.
/// To get extended error information, call GetLastError.</returns>
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DuplicateToken(
IntPtr existingTokenHandle,
SecurityImpersonationLevel securityImpersonationLevel,
out IntPtr duplicateTokenHandle);
/// <summary>
/// Closes the handle.
/// </summary>
/// <param name="handle">The handle.</param>
/// <returns>True if the function succeeds, false if the function fails.
/// To get extended error information, call GetLastError.</returns>
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseHandle(IntPtr handle);
紧随其后
IntPtr token;
if (!NativeMethods.LogonUser(
this.userName,
this.domain,
this.password,
NativeMethods.LogonType.NewCredentials,
NativeMethods.LogonProvider.Default,
out token))
throw new Win32Exception();
try
IntPtr tokenDuplicate;
if (!NativeMethods.DuplicateToken(
token,
NativeMethods.SecurityImpersonationLevel.Impersonation,
out tokenDuplicate))
throw new Win32Exception();
try
using (WindowsImpersonationContext impersonationContext =
new WindowsIdentity(tokenDuplicate).Impersonate())
// Do stuff with your share here.
impersonationContext.Undo();
return;
finally
if (tokenDuplicate != IntPtr.Zero)
if (!NativeMethods.CloseHandle(tokenDuplicate))
// Uncomment if you need to know this case.
////throw new Win32Exception();
finally
if (token != IntPtr.Zero)
if (!NativeMethods.CloseHandle(token))
// Uncomment if you need to know this case.
////throw new Win32Exception();
【讨论】:
我最终没有关注您的实施,您回答了我的问题的链接(我从没想过要查看那个问题)。谢谢!!! 我知道这是您的旧帖子,但为什么需要创建重复令牌。 @Scott,希望我知道一个权威的答案。这是我进行了一些研发(剽窃和部署)的代码,它有效,所以当时我没有质疑它。我能找到的最接近的答案是support.microsoft.com/kb/306158/en-us(记录不充分)和ms-news.net/f1056/why-duplicatetoken-6767285.html。 我也一直在与这个问题作斗争,在 MSDN 上阅读 advapi32.dll 仅用于对本地计算机进行身份验证后,我几乎忽略了所有使用它的解决方案,但不能忽略如何有很多。我认为重复令牌的关键在于将 LogonType 传递给传递“NewCredentials”的第一个调用,如果您阅读此类型的注释 - “此登录类型允许调用者克隆其当前令牌并为出站连接指定新凭据",因此第二部分必须是出站连接的凭据。 我必须添加“使用 System.Security.Principal;”对于我的 .Net 4 项目以上是关于在 C# 中访问 Windows 中受密码保护的网络驱动器?的主要内容,如果未能解决你的问题,请参考以下文章