如果在AD中要修改一个域用户的密码,而当前的操作用户并不具有域管理员的身份,将不会成功。所以说,要完成这个功能,必须能模拟域管理员的身份。下面提供了一个身份模拟类,代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Principal;
using System.Runtime.InteropServices;
namespace SystemUser
{
public class IdentityImpersonation
{
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
// 要模拟的用户的用户名、密码、域(机器名)
private String _sImperUsername;
private String _sImperPassword;
private String _sImperDomain;
// 记录模拟上下文
private WindowsImpersonationContext _imperContext;
private IntPtr _adminToken;
private IntPtr _dupeToken;
// 是否已停止模拟
private Boolean _bClosed;
public IdentityImpersonation(String impersonationUsername, String impersonationPassword, String impersonationDomain)
{
_sImperUsername = impersonationUsername;
_sImperPassword = impersonationPassword;
_sImperDomain = impersonationDomain;
_adminToken = IntPtr.Zero;
_dupeToken = IntPtr.Zero;
_bClosed = true;
}
~IdentityImpersonation()
{
if (!_bClosed)
{
StopImpersonate();
}
}
public Boolean BeginImpersonate()
{
Boolean bLogined = LogonUser(_sImperUsername, _sImperDomain, _sImperPassword, 2, 0, ref _adminToken);
if (!bLogined)
{
return false;
}
Boolean bDuped = DuplicateToken(_adminToken, 2, ref _dupeToken);
if (!bDuped)
{
return false;
}
WindowsIdentity fakeId = new WindowsIdentity(_dupeToken);
_imperContext = fakeId.Impersonate();
_bClosed = false;
return true;
}
public void StopImpersonate()
{
_imperContext.Undo();
CloseHandle(_dupeToken);
CloseHandle(_adminToken);
_bClosed = true;
}
}
}
下面是IdentityImpersonation类使用的一个小例子:
public void setPassWord(string guid, string password)
{
try
{
string imperPass = ConfigurationManager.AppSettings["ADPassword"];
string imperDomain = getDomainName();
IdentityImpersonation imper = new IdentityImpersonation("Administrator", imperPass, imperDomain);
//开始模拟
imper.BeginImpersonate();
DirectoryEntry myDE = new DirectoryEntry(_getLDAPpathbyGUID(guid));
ActiveDs.IADsUser user = (IADsUser)myDE.NativeObject;
user.SetPassword(password);
//停止模拟
imper.StopImpersonate();
}
catch(Exception ex)
{
throw new Exception("设置密码失败!", ex);
}
}