我有一個字符串,我從LDAP獲取Active Directory組成員資格,我需要解析它以檢查用戶是否是AD組的成員。有沒有可以爲我解析的類?是否有.NET類可以解析CN =字符串出LDAP?
例子:
CN=Foo Group Name,DC=mydomain,DC=com
我有一個字符串,我從LDAP獲取Active Directory組成員資格,我需要解析它以檢查用戶是否是AD組的成員。有沒有可以爲我解析的類?是否有.NET類可以解析CN =字符串出LDAP?
例子:
CN=Foo Group Name,DC=mydomain,DC=com
此外,如果你查詢AD的一組成員,你就可以比較所有成員的distinguishedName的直接的,而不解析通過System.DirectoryServices
命名空間的DirectoryEntry
類代碼。
否則,我只是不知道這樣的類別的地方。 =)
希望這有助於無論如何不知何故!
編輯#1
這裏是我從中學到了很多與AD和System.DirectoryServices
命名工作的鏈接:Howto: (Almost) Everything In Active Directory via C#
我將在幾天內爲您提供的樣本代碼,如果您仍然需要它,我將使用System.DirectoryServices.DirectorySearcher
對象類來檢索組的成員。
我希望這個鏈接將幫助你,因爲它爲我做! =)
編輯#2
下面的代碼示例中,我告訴你。這應該使它能夠更有效地查詢AD,而不必工作在AD和AD之間。
public IList<string> GetMembers(string groupName) {
if (string.IsNullOrEmpty(groupName))
throw new ArgumentNullException("groupName");
IList<string> members = new List<string>();
DirectoryEntry root = new DirectoryEntry(@"LDAP://my.domain.com");
DirectorySearcher searcher = new DirectorySearcher();
searcher.SearchRoot = root;
searcher.SearchScope = SearchScope.Subtree;
searcher.PropertiesToLoad.Add("member");
searcher.Filter = string.Format("(&(objectClass=group)(sAMAccountName={0}))", groupName);
SearchResult result = searcher.FindOne();
DirectoryEntry groupFound = result.GetDirectoryEntry();
for (int index = 0; index < ((object[])groupFound.Properties["member"].Value).Length; ++index)
members.Add((string)((object[])groupFound.Properties["member"].Value)[index]);
return members;
}
聲明:提供該代碼原樣。我在我的本地機器上測試過它,它工作得很好。但是由於我不得不在這裏重新輸入它,因爲我不能複製粘貼它,所以我在輸入時可能會犯一些錯誤,而這些錯誤我都沒有發生過。
這對我來說工作得很好,問題在於與AD一起來回的昂貴往返成本。嘗試一種方式一次性獲取它們。 – 2010-09-30 20:24:46
如果您使用的是.NET 3.5或可以使用'System.Linq'命名空間,那麼您可能有興趣關注Codeplex上Bart De Smet的LINQ to AD項目。這允許您使用LINQ來針對AD進行查詢。事實上,完成圖書館還有一些工作要做,但最重要的方面在他的開源代碼中。 – 2010-09-30 20:48:29
如果您想要一個組的直接成員,請針對該組的DN調用「DirectorySearcher」,並獲取其「成員」屬性以獲取DN列表。如果你想要在一個組中嵌套組成員,可以獲得'tokenGroups'屬性來獲取對象SID列表。我寫了一段時間回來:http://explodingcoder.com/blog/content/how-query-active-directory-security-group-membership – spoulson 2010-09-30 22:11:16
如果你不想增加額外的依賴關係,只是想解析字符串..
這種類型的字符串可以很容易地只用string.Split進行解析。爲了得到CN值,將會是這樣的......
string[] split = "CN=Foo Group Name,DC=mydomain,DC=com".Split(',');
List<string> cnValues = new List<string>();
foreach(string pair in split){
string[] keyValue=pair.Split('=');
if(keyValue[0]=="CN")
cnValues.Add(keyValue[1]);
}
+1這回答了這個問題,是一個很好的解決方案。 – 2010-10-01 18:48:04
對於那些回讀,這種解決方案對於生產環境是不夠的 - [RFC](http://www.rfc-archive.org/getrfc.php?rfc=4514)指定值可以被引用,還有人物逃脫規則。另外,用這種格式的逗號分割字符串是非常危險的。 – 2011-03-23 18:29:03
這些被稱爲辨別名稱。
CodeProject上有出現做你需要什麼解析器項目:http://www.codeproject.com/KB/IP/dnparser.aspx
它也被包裝成github項目和nuget包以方便訪問。 https://github.com/picrap/DNParser/blob/master/README.md – 2018-03-02 20:09:37
Using System.DirectoryServices;
namespace GetGroups
{
public string GetGroupName(string LDAPGroupEntry)
{
// LDAPGroupEntry is in the form "LDAP://CN=Foo Group Name,DC=mydomain,DC=com"
DirectoryEntry grp = new DirectoryEntry(LDAPGroupEntry);
return grp.Properties["Name"].Value.ToString();
}
}
要回答這個問題的解析,使用的PInvoke與DsGetRdnW
。有關代碼,請參閱我對另一個問題的回答:https://stackoverflow.com/a/11091804/628981。
但它聽起來像你做錯了。首先,獲取目標羣組的SID:
string targetGroupName = //target group name;
DirectorySearcher dsTargetGroup = new DirectorySearcher();
dsTargetGroup.Filter = string.Format("(sAMAccountName={0})", targetGroupName);
SearchResult srTargetGroup = dsTargetGroup.FindOne();
DirectoryEntry deTargetGroup = srTargetGroup.GetDirectoryEntry();
byte[] byteSid = (byte[])deTargetGroup.Properties["objectSid"].Value;
SecurityIdentifier targetGroupSid = new SecurityIdentifier(byteSid, 0);
然後,這取決於你有什麼。如果用戶正在運行您的應用程序(或通過身份驗證到您的網站/服務),然後枚舉令牌中的SID。例如,在桌面應用程序中使用WindowsIdentity.GetCurrent().Groups
。否則,你就需要獲得一個DirectoryEntry的用戶,然後獲得tokenAttributes
屬性像spoulson建議:
DirectoryEntry deTargetUser = //target user;
DirectorySearcher dsTargetUser = new DirectorySearcher(deTargetUser);
dsTargetUser.SearchScope = SearchScope.Base; //tokenGroups is a constructed attribute, so have to ask for it while performing a search
dsTargetUser.Filter = "(objectClass=*)"; //this is closest thing I can find to an always true filter
dsTargetUser.PropertiesToLoad.Add("tokenGroups");
SearchResult srTargetUser = dsTargetUser.FindOne();
foreach(byte[] byteGroupSid in srTargetUser.Properties["tokenGroups"])
{
SecurityIdentifier groupSid = new SecurityIdentifier(byteGroupSid, 0);
if(groupSid == targetGroupSid)
{
//success
}
}
萬一你需要從一個SID得到一個DirectoryEntry,你可以得到搜索字符串:
public static string GetSIDSearchFilter(SecurityIdentifier sid)
{
byte[] byteSid = new byte[sid.BinaryLength];
sid.GetBinaryForm(byteSid, 0);
return string.Format("(objectSid={0})", BuildFilterOctetString(byteSid));
}
public static string BuildFilterOctetString(byte[] bytes)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
sb.AppendFormat("\\{0}", bytes[i].ToString("X2"));
}
return sb.ToString();
}
要解析DistinquishedName,您必須注意轉義字符。這裏有一個方法可以正確解析字符串並返回一個鍵值對列表。
public static List<KeyValuePair<string, string>> ParseDistinguishedName(string input)
{
int i = 0;
int a = 0;
int v = 0;
var attribute = new char[50];
var value = new char[200];
var inAttribute = true;
string attributeString, valueString;
var names = new List<KeyValuePair<string, string>>();
while (i < input.Length)
{
char ch = input[i++];
switch(ch)
{
case '\\':
value[v++] = ch;
value[v++] = input[i++];
break;
case '=':
inAttribute = false;
break;
case ',':
inAttribute = true;
attributeString = new string(attribute).Substring(0, a);
valueString = new string(value).Substring(0, v);
names.Add(new KeyValuePair<string, string>(attributeString, valueString));
a = v = 0;
break;
default:
if (inAttribute)
{
attribute[a++] = ch;
}
else
{
value[v++] = ch;
}
break;
}
}
attributeString = new string(attribute).Substring(0, a);
valueString = new string(value).Substring(0, v);
names.Add(new KeyValuePair<string, string>(attributeString, valueString));
return names;
}
static void Main(string[] args)
{
const string TestString = "CN=BY2STRAKRJOB2,OU=MSNStorage,OU=RESOURCE,OU=PRODUCTION,DC=phx,DC=gbl,STREET=street address,L=locality Name,C=Country Name,UID=user id,STUFF=\\,\\.\\+\"<>;\\=\\0A";
var names = ParseDistinguishedName(TestString);
foreach (var pair in names)
{
Console.WriteLine("{0} = {1}", pair.Key, pair.Value);
}
}
真棒 - 感謝老兄! – 2015-01-26 01:58:19
非常喜歡這種方法 - 儘管它不修剪屬性名稱中的空白,並且我也有一些引用值的問題,例如O =「VeriSign,Inc.」 - 所以我稍微調整了一些東西https://gist.github.com/davetransom/e9c58b96afa46d4c75a0 – 2015-04-10 23:55:00
聽起來像是你需要一個正則表達式 - 正則表達式應該做的工作...... – 2010-09-30 18:47:40
見http://stackoverflow.com/questions/356480/c-extracting-a-name-from-a-string – nos 2010-09-30 18:55:19
我不想使用RegEx,因爲我不想承擔測試成本。感謝你的建議。 – 2010-09-30 19:55:53