我的应用程序使用网络上的共享目录(Windows),并且我希望仅在给定用户和密码的网络上提供该共享。 有没有办法在对此网络资源进行任何操作之前通过身份验证? *我没有使用域名。
非常感谢你!
答案 0 :(得分:1)
我不完全确定如何传递IO操作的凭据,但通常我会使用模拟类来模拟或委派特定代码块的用户凭据。
E.g:
/// <summary>
/// Provides a mechanism for impersonating a user. This is intended to be disposable, and
/// used in a using ( ) block.
/// </summary>
public class Impersonation : IDisposable
{
#region Externals
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(
string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
out IntPtr phToken);
[DllImport("advapi32.dll", SetLastError = true)]
private extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int
SECURITY_IMPERSONATION_LEVEL, out IntPtr DuplicateTokenHandle);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
#endregion
#region Fields
private IntPtr token;
private IntPtr tokenDuplicate;
private WindowsIdentity identity;
private WindowsImpersonationContext context;
private readonly string domain;
private readonly string username;
private readonly string password;
private ImpersonationLevel level;
#endregion
#region Constructor
/// <summary>
/// Initialises a new instance of <see cref="Impersonation"/>.
/// </summary>
/// <param name="domain">The domain of the target user.</param>
/// <param name="username">The target user to impersonate.</param>
/// <param name="password">The target password of the user to impersonate.</param>
public Impersonation(string domain, string username, string password)
{
this.domain = domain;
this.username = username;
this.password = password;
this.level = ImpersonationLevel.Impersonation;
Logon();
}
/// <summary>
/// Initialises a new instance of <see cref="Impersonation"/>.
/// </summary>
/// <param name="domain">The domain of the target user.</param>
/// <param name="username">The target user to impersonate.</param>
/// <param name="password">The target password of the user to impersonate.</param>
/// <param name="level">The security level of this impersonation.</param>
public Impersonation(string domain, string username, string password, ImpersonationLevel level)
{
this.domain = domain;
this.username = username;
this.password = password;
this.level = level;
Logon();
}
#endregion
#region Methods
/// <summary>
/// Reverts the impersonation.
/// </summary>
public void Dispose()
{
if (context != null)
context.Undo();
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
}
/// <summary>
/// Performs the logon.
/// </summary>
private void Logon()
{
if (LogonUser(username, domain, password, 2, 0, out token))
{
if (DuplicateToken(token, (int)level, out tokenDuplicate))
{
identity = new WindowsIdentity(tokenDuplicate);
context = identity.Impersonate();
}
else
{
throw new SecurityException("Unable to impersonate the user.");
}
}
else
{
throw new SecurityException("The login details you have entered were incorrect.");
}
}
#endregion
}
/// <summary>
/// Defines the possible security levels for impersonation.
/// </summary>
public enum ImpersonationLevel
{
/// <summary>
/// Anonymous access, the process is unable to identify the security context.
/// </summary>
Anonymous = 0,
/// <summary>
/// The process can identify the security context.
/// </summary>
Identification = 1,
/// <summary>
/// The security context can be used to access local resources.
/// </summary>
Impersonation = 2,
/// <summary>
/// The security context can be used to access remote resources.
/// </summary>
Delegation = 3
}
现在,它确实涉及一点P / Invoke,但最终结果是:
class Program
{
static void Main(string[] args)
{
using (var impersonation = new Impersonation("domain", "username", "password", ImpersonationLevel.Delegation))
{
// Do remote operations here.
}
}
}
对于给定的代码段,您可以模拟所需的用户来执行操作。如果在using块中使用,则在执行该段代码之后,将恢复模拟并关闭句柄。
如果您不使用使用区块,则需要确保致电Dispose
以清除所有内容。