Ryk*_*Ryk 26 c# model-view-controller asp.net-mvc active-directory
我在MVC Web应用程序中使用c#on .Net 4时出现问题,当我查询Active Directory时,我经常收到错误:尝试访问已卸载的appdomain.(来自HRESULT的异常:0x80131014).
奇怪的是,它会在一段时间内完美无缺地工作,然后它才会开始发生,然后再次消失.
我对函数进行了一些修改以使其工作,但它们似乎都失败了.我想知道我做错了什么,或者是否有更好的方法来做.
这是我当前的函数,它将接受loginId和PrincipalContext.loginId可以是用户DisplayName,即"John Smith",也可以是DOMAINNAME\josmi.默认设置是使用其名字的前2个字母,然后使用其姓氏的前3个字母.如果不是这样,那里有一张支票.这部分如果罚款.
public List<ADGroup> GetMemberGroups(string loginId, PrincipalContext principalContext, int tries = 0)
{
var result = new List<ADGroup>();
try
{
var samAccountName = "";
if (loginId.Contains(" "))
{
var fName = loginId.Split(Char.Parse(" "))[0].ToLower();
var sName = loginId.Split(Char.Parse(" "))[1].ToLower();
if (sName.Trim().Length == 2)
samAccountName = string.Format("{0}{1}", fName.StartsWith(".") ? fName.Substring(0, 4) : fName.Substring(0, 3), sName.Substring(0, 2));
else
samAccountName = string.Format("{0}{1}", fName.StartsWith(".") ? fName.Substring(0, 3) : fName.Substring(0, 2), sName.Substring(0, 3));
}
else
samAccountName = loginId.Substring(loginId.IndexOf(@"\") + 1);
var authPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, samAccountName);
if (authPrincipal == null)
throw new Exception(string.Format("authPrincipal is null for loginId - {0}", loginId));
var firstLevelGroups = authPrincipal.GetGroups();
AddGroups(firstLevelGroups, ref result);
}
catch
{
if (tries > 5)
throw;
tries += 1;
System.Threading.Thread.Sleep(1000);
GetMemberGroups(loginId, principalContext, tries);
}
return result;
}
private void AddGroups(PrincipalSearchResult<Principal> principal, ref List<ADGroup> returnList)
{
foreach (var item in principal)
{
if (item.GetGroups().Count() > 0)
AddGroups(item.GetGroups(), ref returnList);
returnList.Add(new ADGroup(item.SamAccountName, item.Sid.Value));
}
}
Run Code Online (Sandbox Code Playgroud)
这个函数被调用如下:
MembershipGroups = ad.GetMemberGroups(user.SamAccountName, new PrincipalContext(ContextType.Domain));
Run Code Online (Sandbox Code Playgroud)
我有时得到的错误是:
System.AppDomainUnloadedException:尝试访问已卸载的appdomain.(来自HRESULT的异常:0x80131014)System.StubHelpers.StubHelpers.InternalGetCOMHRExceptionObject(Int32hr,IntPtr pCPCMD,Object pThis)位于System.DuboryServices.AccountManagement的System.StubHelpers.StubHelpers.GetCOMHRExceptionObject(Int32hr,IntPtr pCPCMD,Object pThis). System.DirectoryServices.AccountManagement.ADStoreCtx.get_UserSuppliedServerName()位于System.DirectoryServices.AccountManagement.ADDNLinkedAttrSet.BuildPathFromDN(String dn)的System.DirectoryServices.AccountManagement.ADStoreCtx.LoadDomainInfo()中的UnsafeNativeMethods.IADsPathname.Retrieve(Int32 lnFormatType).
1.MoveNext() at System.DirectoryServices.AccountManagement.FindResultEnumeratorSystemServices.AccountManagement.ADDNLinkedAttrSet.MoveNextPrimaryGroupDN()at System.DirectoryServices.AccountManagement.ADDNLinkedAttrSet.MoveNext()at System.DirectoryServices.AccountManagement.FindResultEnumerator 1.System.Collections.IEnumerator.MoveNext()
通过System.DirectoryServices.AccountManagement中的反射器查看内部类"UnsafeNativeMethods"是在本机代码中实现的,因此UserSuppliedServerName是一个级别,我可以继续而不看CLR VM,(坦率地说我甚至不确定如何做到这一点)似乎一个节点无法返回其主要组,所以也许考虑其他实现,经过一些谷歌搜索我遇到这些可能会有所帮助
Active Directory和嵌套组 这个可能有希望继承代码示例..
public IList<string> FindUserGroupsLdap(string username)
{
// setup credentials and connection
var credentials = new NetworkCredential("username", "password", "domain");
var ldapidentifier = new LdapDirectoryIdentifier("server", 389, true, false);
var ldapConn = new LdapConnection(ldapidentifier, credentials);
// retrieving the rootDomainNamingContext, this will make sure we query the absolute root
var getRootRequest = new SearchRequest(string.Empty, "objectClass=*", SearchScope.Base, "rootDomainNamingContext");
var rootResponse = (SearchResponse)ldapConn.SendRequest(getRootRequest);
var rootContext = rootResponse.Entries[0].Attributes["rootDomainNamingContext"][0].ToString();
// retrieve the user
string ldapFilter = string.Format("(&(objectCategory=person)(sAMAccountName={0}))", username);
var getUserRequest = new SearchRequest(rootContext, ldapFilter, SearchScope.Subtree, null);
var userResponse = (SearchResponse)ldapConn.SendRequest(getUserRequest);
// send a new request to retrieve the tokenGroups attribute, we can not do this with our previous request since
// tokenGroups needs SearchScope.Base (dont know why...)
var tokenRequest = new SearchRequest(userResponse.Entries[0].DistinguishedName, "(&(objectCategory=person))", SearchScope.Base, "tokenGroups");
var tokenResponse = (SearchResponse)ldapConn.SendRequest(tokenRequest);
var tokengroups = tokenResponse.Entries[0].Attributes["tokenGroups"].GetValues(typeof(byte[]));
// build query string this query will then look like (|(objectSid=sid)(objectSid=sid2)(objectSid=sid3))
// we need to convert the given bytes to a hexadecimal representation because thats the way they
// sit in ActiveDirectory
var sb = new StringBuilder();
sb.Append("(|");
for (int i = 0; i < tokengroups.Length; i++)
{
var arr = (byte[])tokengroups[i];
sb.AppendFormat("(objectSid={0})", BuildHexString(arr));
}
sb.Append(")");
// send the request with our build query. This will retrieve all groups with the given objectSid
var groupsRequest = new SearchRequest(rootContext, sb.ToString(), SearchScope.Subtree, "sAMAccountName");
var groupsResponse = (SearchResponse)ldapConn.SendRequest(groupsRequest);
// loop trough and get the sAMAccountName (normal, readable name)
var userMemberOfGroups = new List<string>();
foreach (SearchResultEntry entry in groupsResponse.Entries)
userMemberOfGroups.Add(entry.Attributes["sAMAccountName"][0].ToString());
return userMemberOfGroups;
}
private string BuildHexString(byte[] bytes)
{
var sb = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
sb.AppendFormat("\\{0}", bytes[i].ToString("X2"));
return sb.ToString();
}
Run Code Online (Sandbox Code Playgroud)这些更多用于信息目的
我不知道PrincipalContext在这里如何进行传递,但是当我遇到此错误时,我在自己的代码和研究中注意到的一件事是:
PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain);
UserPrincipal oUserPrincipal = UserPrincipal.FindByIdentity(oPrincipalContext , strUserName);
Run Code Online (Sandbox Code Playgroud)
strUserName一些用户在哪里,即DOMAIN\johndoe
我正在调用该代码(在单独的函数中),然后将UserPrincipal对象返回为up并将其传递给:
using (PrincipalSearchResult<Principal> result = up.GetGroups())
{
// do something with result, here
}
Run Code Online (Sandbox Code Playgroud)
result不会为null,但是在检查了该条件之后,我检查了是否为result.Count() > 0,那才是失败的条件(有时-尽管我可以通过单击应用程序中一个特定的选项卡来重新创建条件,但条件是此代码-即使同一代码被称为我的应用的onload并且没有问题)。的Message财产result为Attempted to access an unloaded appdomain. (Exception from HRESULT: 0x80131014)。
我在与此类似的帖子中发现,我所要做的就是在我的中指定域PrincipalContext。由于我无法进行硬编码,因此在开发,测试和生产环境之间移动代码时,这些环境对于每个环境都有不同的域,因此我可以将其指定为Environment.UserDomainName:
PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, Environment.UserDomainName);
Run Code Online (Sandbox Code Playgroud)
对我来说,这消除了错误。
| 归档时间: |
|
| 查看次数: |
19823 次 |
| 最近记录: |