我有代码可以为任何特定用户从 AD 返回组。在我的开发箱上本地工作得很好。当我尝试在 Web 服务器上运行它时,它不会完成代码但会引发错误然后返回。我虽然这可能与权限有关,所以当代码完成获取组时,我添加了一个模拟管理员帐户的部分,它撤消了模拟。该代码不会引发错误,但它也不会返回组列表。
public static List<GroupPrincipal> GetUserGroups(string userName)
{
bool isImper = impersonateValidUser("user", "domain", "password");
List<GroupPrincipal> result = new List<GroupPrincipal>();
// establish domain context
PrincipalContext yourDomain = new PrincipalContext(ContextType.Domain,"WYSD");
// find your user
UserPrincipal user = UserPrincipal.FindByIdentity(yourDomain, userName);
// if found - grab its groups
if (user != null)
{
PrincipalSearchResult<Principal> groups = user.GetAuthorizationGroups();
// iterate over all groups
foreach (Principal p in groups)
{
// make sure to add only group principals
if (p is GroupPrincipal)
{
result.Add((GroupPrincipal)p);
}
}
}
undoImpersonation();
try
{
return result;
}
catch (Exception ex)
{
Log.WriteLog("Error in retriving form data: " + ex.Message);
Thread.Sleep(1000);
return GetUserGroups(userName);
}
}
捕获中的Thread.Sleep
用于解决目前 .NET 4.0 中的问题。如果我在本地使用模拟或不模拟的代码,它工作正常。模拟代码如下:
public static bool impersonateValidUser(String userName, String domain, String password)
{
System.Security.Principal.WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if(userName.Contains("\\")){
userName = userName.Substring(userName.LastIndexOf("\\") + 1);
}
if (LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new System.Security.Principal.WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
return true;
else
return false;
}
else
return false;
}
else
return false;
}
public static void undoImpersonation()
{
impersonationContext.Undo();
}
#region | Property |
// property getters/setters
public string DomainName { get; set; }
public string LoginPath { get; set; }
public string LoginUsername { get; set; }
public string LoginPassword { get; set; }
public System.DirectoryServices.AuthenticationTypes AuthenticationType { get; set; }
public System.DirectoryServices.DirectoryEntry Ad { get { return Ad; } set { Ad = value; } }
#endregion
#region | Impersonation via interop |
//need to import from COM via InteropServices to do the impersonation when saving the details
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
static System.Security.Principal.WindowsImpersonationContext impersonationContext;
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern int LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
public extern static int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);
#endregion
现在我想问题是,首先我是否需要模拟,如果不需要,为什么代码不起作用。其次,如果我需要模仿,为什么我不取回我的群组?