.net下模拟不同身份登陆以获取不同权限" (.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
{
///

1<summary>   
2/// This logon type is intended for users who will be interactively using the computer, such as a user   
3/// being logged on by a terminal server, remote shell, or similar process. This logon type has the   
4/// additional expense of caching logon information for disconnected operation, and is therefore   
5/// inappropriate for some client/server applications, such as a mail server.   
6/// </summary>

LOGON32_LOGON_INTERACTIVE = 2,

///

1<summary>   
2/// This logon type is intended for high performance servers to authenticate clear text passwords.   
3/// The LogonUser function does not cache credentials for this logon type.   
4/// </summary>

LOGON32_LOGON_NETWORK = 3,

///

1<summary>   
2/// This logon type is intended for batch servers, where processes may be executing on behalf of a user   
3/// without their direct intervention; or for higher performance servers that process many clear-text   
4/// authentication attempts at a time, such as mail or web servers. The LogonUser function does not cache   
5/// credentials for this logon type.   
6/// </summary>

LOGON32_LOGON_BATCH = 4,

///

1<summary>   
2/// Indicates a service-type logon. The account provided must have the service privilege enabled.   
3/// </summary>

LOGON32_LOGON_SERVICE = 5,

///

1<summary>   
2/// This logon type is intended for GINA DLLs logging on users who will be interactively using the computer.   
3/// This logon type allows a unique audit record to be generated that shows when the workstation was unlocked.   
4/// </summary>

LOGON32_LOGON_UNLOCK = 7,

///

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

LOGON32_LOGON_NETWORK_CLEARTEXT = 8,

///

1<summary>   
2/// Windows XP/2000: This logon type allows the caller to clone its current token and specify new credentials   
3/// for outbound connections. The new logon session has the same local identity, but uses different credentials   
4/// for other network connections.   
5/// This logon type is supported only by the LOGON32_PROVIDER_WINNT50 logon provider.   
6/// </summary>

LOGON32_LOGON_NEW_CREDENTIALS = 9
};

public enum LogonProvider : int
{
///

1<summary>   
2/// Use the standard logon provider for the system. The default security provider is NTLM.   
3/// Windows XP: The default provider is negotiate, unless you pass NULL for the domain name and   
4/// the user name is not in UPN format. In this case the default provider is NTLM.   
5/// </summary>

LOGON32_PROVIDER_DEFAULT = 0,

///

1<summary>   
2/// Use the Windows NT 3.5 logon provider.   
3/// </summary>

LOGON32_PROVIDER_WINNT35 = 1,

///

1<summary>   
2/// Use the NTLM logon provider.   
3/// </summary>

LOGON32_PROVIDER_WINNT40 = 2,

///

1<summary>   
2/// Windows XP/2000: Use the negotiate logon provider.   
3/// </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
//
}

///

1<summary>   
2/// The ImpersonateUser function attempts to log a user on to the local computer.   
3/// The local computer is the computer from which ImpersonateUser was called.   
4/// You cannot use ImpersonateUser to log on to a remote computer.   
5/// You specify the user with a user name and domain, and authenticate the user with a clear-text password.   
6/// If the function succeeds, you receive a handle to a token that represents the logged-on user.   
7/// You can then use this token handle to impersonate the specified user, or in most cases,   
8/// to create a process running in the context of the specified user.   
9/// </summary>

///

1<param name="strDomain"/>

/// specifies the name of the domain or server whose account database contains the strLogin account.
///
///

1<param name="strLogin"/>

specifies the name of the user.
///

1<param name="strPwd"/>

specifies the clear-text password for the user account specified by strLogin.
///

1<param name="logonType"/>

Specifies the type of logon operation to perform.
///

1<param name="logonProvider"/>

Specifies the logon provider.
///

 1<example>   
 2/// //Add System.Security.dll   
 3/// //using System.Security.Principal;   
 4///   
 5/// string strDomain=ConfigurationSettings.AppSettings["mSALoginDomainName"];   
 6/// string strUser=ConfigurationSettings.AppSettings["mSALoginDomainUser"];   
 7/// string strPassword=ConfigurationSettings.AppSettings["mSALoginDomainPassword"];   
 8///   
 9/// WindowsImpersonationContext impContext = null;   
10/// try   
11/// {   
12/// impContext = NetworkSecurity.ImpersonateUser(strDomain,strUser,strPassword,   
13/// LogonType.LOGON32_LOGON_SERVICE,   
14/// LogonProvider.LOGON32_PROVIDER_DEFAULT);   
15/// }   
16/// catch   
17/// {   
18///   
19/// }   
20///   
21/// //work under this logined user   
22///   
23/// impContext.Undo();   
24/// </example>

///

1<returns>   
2/// </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);
}
}
}
}

Published At
Categories with Web编程
Tagged with
comments powered by Disqus