.net下模拟不同身份登陆以获取不同权限"

不管是asp.net、web service还是window service,程序运行的时候只有本地计算机的部分权限,有时候需要更大的权限,比如读写某台服务器或域中的一台计算机上的文件等,这就需要更大的权限,比如域帐户权限。

通过获取不同身份的 WindowsImpersonationContext对象,可以模拟不同用户登陆,请看我生成的NetworkSecurity类的
public static WindowsImpersonationContext ImpersonateUser(string strDomain,

              string strLogin,

              string strPwd,

              LogonType logonType,

              LogonProvider logonProvider)

NetworkSecurity.cs源代码如下:

/*
 *  Author : TongWei
 *  Date : 2005-1-25
 *  Rights : China Netwave Inc.@2005
 */

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;

namespace CNW.OMP.Common.Utility
{
 public 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 operation, and is therefore
  /// 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 clear text 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; or for higher performance servers that process many clear-text
  /// 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 intended for GINA DLLs logging on users who will be interactively using the computer.
  /// This logon type allows a unique audit record to be generated that shows when the workstation was unlocked.
  /// </summary>
  LOGON32_LOGON_UNLOCK = 7,

  /// <summary>
  /// Windows XP/2000:  This logon type preserves the name and password in the authentication packages,
  /// allowing the server to make connections to other network servers while impersonating the client.
  /// This allows a server to accept clear text credentials from a client, call LogonUser, verify that
  /// the user can access the system across the network, and still communicate with other servers.
  /// </summary>
  LOGON32_LOGON_NETWORK_CLEARTEXT = 8,

  /// <summary>
  /// Windows XP/2000:  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 identity, but uses different credentials
  /// for other network connections.
  /// This logon type is supported only by the LOGON32_PROVIDER_WINNT50 logon provider.
  /// </summary>
  LOGON32_LOGON_NEW_CREDENTIALS = 9
 };

 public enum LogonProvider : int
 {
  /// <summary>
  /// Use the standard logon provider for the system. The default security provider is NTLM.
  /// Windows XP:   The default 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.
  /// </summary>
  LOGON32_PROVIDER_DEFAULT = 0,

  /// <summary>
  /// Use the Windows NT 3.5 logon provider.
  /// </summary>
  LOGON32_PROVIDER_WINNT35 = 1,

  /// <summary>
  /// Use the NTLM logon provider.
  /// </summary>
  LOGON32_PROVIDER_WINNT40 = 2,

  /// <summary>
  /// Windows XP/2000:  Use the negotiate logon provider.
  /// </summary>
  LOGON32_PROVIDER_WINNT50 = 3
 };

 class SecuUtil32
 {
  [DllImport("advapi32.dll", SetLastError=true)]
  public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
   int dwLogonType, int dwLogonProvider, ref IntPtr TokenHandle);

  [DllImport("kernel32.dll", CharSet=CharSet.Auto)]
  public extern static bool CloseHandle(IntPtr handle);

  [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
  public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
   int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
 }

 public class NetworkSecurity
 {
  public NetworkSecurity()
  {
   //
   // TODO: Add constructor logic here
   //
  }

  /// <summary>
  /// The ImpersonateUser function attempts to log a user on to the local computer.
  /// The local computer is the computer from which ImpersonateUser was called.
  /// You cannot use ImpersonateUser to log on to a remote computer.
  /// You specify the user with a user name and domain, and authenticate the user with a clear-text password.
  /// If the function succeeds, you receive a handle to a token that represents the logged-on user.
  /// You can then use this token handle to impersonate the specified user, or in most cases,
  /// to create a process running in the context of the specified user.
  /// </summary>
  /// <param name="strDomain">
  /// specifies the name of the domain or server whose account database contains the strLogin account.
  /// </param>
  /// <param name="strLogin">specifies the name of the user.</param>
  /// <param name="strPwd">specifies the clear-text password for the user account specified by strLogin.</param>
  /// <param name="logonType">Specifies the type of logon operation to perform.</param>
  /// <param name="logonProvider">Specifies the logon provider.</param>
  /// <example>
  /// //Add System.Security.dll
  /// //using System.Security.Principal;
  ///
  /// string strDomain=ConfigurationSettings.AppSettings["mSALoginDomainName"];
  /// string strUser=ConfigurationSettings.AppSettings["mSALoginDomainUser"];
  /// string strPassword=ConfigurationSettings.AppSettings["mSALoginDomainPassword"];
  ///
  /// WindowsImpersonationContext impContext = null;
  /// try
  /// {
  ///  impContext = NetworkSecurity.ImpersonateUser(strDomain,strUser,strPassword,
  ///     LogonType.LOGON32_LOGON_SERVICE,
  ///     LogonProvider.LOGON32_PROVIDER_DEFAULT);
  /// }
  /// catch
  /// {
  /// 
  /// }
  /// 
  /// //work under this logined user
  /// 
  /// impContext.Undo();
  /// </example>
  /// <returns>
  /// </returns>
  public static WindowsImpersonationContext ImpersonateUser(string strDomain,
   string strLogin,
   string strPwd,
   LogonType logonType,
   LogonProvider logonProvider)
  {
   // Initialize tokens
   IntPtr tokenHandle = new IntPtr(0);
   IntPtr dupeTokenHandle = new IntPtr(0);
   tokenHandle = IntPtr.Zero;
   dupeTokenHandle = IntPtr.Zero;
   
   // If domain name was blank, assume local machine
   if (strDomain == "")
    strDomain = System.Environment.MachineName;

   try
   {
    const int SecurityImpersonation = 2;

    // Call LogonUser to obtain a handle to an access token.
    bool returnValue = SecuUtil32.LogonUser(
     strLogin,
     strDomain,
     strPwd,
     (int)logonType,
     (int)logonProvider,
     ref tokenHandle);

    // Did impersonation fail?
    if (false == returnValue)
    {
     int ret = Marshal.GetLastWin32Error();
     // Throw the exception show the reason why LogonUser failed
     string strErr = String.Format("LogonUser failed with error code : {0}", ret);
     throw new ApplicationException(strErr, null);
    }
    
    // Get identity before impersonation
    bool retVal = SecuUtil32.DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle);
    
    // Did DuplicateToken fail?
    if (false == retVal)
    {
     // Close existing handle
     SecuUtil32.CloseHandle(tokenHandle);
     // Throw the exception show the reason why DuplicateToken failed
     throw new ApplicationException("Failed to duplicate token", null);
    }

    // Create new identity using new primary token
    // The token that is passed to the following constructor must
    // be a primary token in order to use it for impersonation.
    WindowsIdentity newId = new WindowsIdentity(dupeTokenHandle);
    WindowsImpersonationContext impersonatedUser = newId.Impersonate();

    return impersonatedUser;
   }
   catch (Exception ex)
   {
    throw new ApplicationException(ex.Message, ex);
   }
   finally
   {
    // Close handle
    if (tokenHandle != IntPtr.Zero)
     SecuUtil32.CloseHandle(tokenHandle);
    if (dupeTokenHandle != IntPtr.Zero)
     SecuUtil32.CloseHandle(dupeTokenHandle);
   }
  }
 }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值