使用C#在操作之前传递服务器共享凭据

问题描述:

我的应用程序在网络上使用共享目录(Windows),并且我想让网络上的共享仅对给定的用户和密码可用。 在对此网络资源进行任何操作之前是否有任何方式通过身份验证? *我没有使用域名。使用C#在操作之前传递服务器共享凭据

非常感谢!

我不完全确定您将如何传递IO操作的凭据,但通常我使用模拟类来模拟或委派特定代码块的用户凭据。

如:

/// <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. 
     } 
    } 
} 

对于给定的代码段,你可以模拟所需的用户执行您的操作。如果在使用块中使用,则在执行该段代码之后,模拟会恢复并且手柄关闭。

如果您不使用使用块,您需要确保您致电Dispose清除所有内容。

+0

我明白了。感谢您的快速响应。 – andySF 2010-10-13 11:15:26