2012-02-16 27 views
0

我們已經使用userProxy obect與Active Directory輕量級目錄服務(AD LDS)與Active Directory同步。我們還在AD LDS中創建用戶類對象。具有多個DirectoryObjectClassAttribute的System.DirectoryServices.AccountManagement.UserPrincipal

UserPrincipal對象似乎僅限於AD中的用戶類對象。我知道我可以基於userProxy類對象創建一個userProxyPrincipal。但我想創建一個對象來處理這兩種情況。

由於在DirectoryObjectClassAttribute的文檔中指定了可以使用多個DirectoryObjectClassAttribute我想知道如何實現這一點。

如果我在自己的UserPrincipal對象上指定了兩個屬性(一個使用「user」,另一個使用「userProxy」),它會編譯,但僅匹配與指定的第一個類相同的對象。 (我試圖交換它們,它總是第一個匹配的)

如果我在一個屬性上指定了兩個DirectoryPropertyAttribute,現在它只匹配與第二個類具有相同類的對象。

所以我看到它可以從一個轉移到另一個,但我不明白如何正確實施它。

有什麼建議嗎?

(對不起,我沒有代碼爲例的,我在家裏,將發佈他們明天第一件事就是在工作中)

更新 - 添加一小段代碼片段

這裏是我的UserProxyPrincipal類

namespace System.DirectoryServices.AccountManagement 
{ 
    [DirectoryRdnPrefix("CN")] 
    [DirectoryObjectClass("userProxy")] 
    [DirectoryObjectClass("user")] 
    public class UserProxyPrincipal : UserPrincipal 
    { 
     public UserProxyPrincipal(PrincipalContext context) 
      : base(context) { } 
     public UserProxyPrincipal(PrincipalContext context, string samAccountName, string password, bool enabled) 
      : base(context, samAccountName, password, enabled) { } 

     public static new UserProxyPrincipal FindByIdentity(PrincipalContext context, string identityValue) 
     { 
      return (UserProxyPrincipal)FindByIdentityWithType(context, typeof(UserProxyPrincipal), identityValue); 
     } 
     public static new UserProxyPrincipal FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue) 
     { 
      return (UserProxyPrincipal)FindByIdentityWithType(context, typeof(UserProxyPrincipal), identityType, identityValue); 
     } 

     [DirectoryProperty("objectSid")] 
     public string ObjectSid 
     { 
      get 
      { 
       var values = ExtensionGet("objectSid"); 
       return ((values != null) && (values.Length > 0) ? values[0].ToString() : null); 
      } 
      set { ExtensionSet("objectSid", value); } 
     } 

     [DirectoryProperty("name")] 
     public new string Name 
     { 
      get 
      { 
       var values = ExtensionGet("name"); 
       return ((values != null) && (values.Length > 0) ? values[0].ToString() : null); 
      } 
      set { ExtensionSet("name", value); } 
     } 
    } 
} 

這裏有一個程序來測試它

namespace FunWith.MTO.Framework.Security 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      PrincipalContext context = new PrincipalContext(ContextType.ApplicationDirectory, "servername.some.domain:636", "DC=dev,DC=local", ContextOptions.SimpleBind); 
      Console.WriteLine("Log AdamUser : {0}", context.ValidateCredentials("AdamUser", "somePassword%")); 
      Console.WriteLine("Log AdProxiedUser : {0}", context.ValidateCredentials("AdProxiedUser", "somePassword;")); 
      var p = UserProxyPrincipal.FindByIdentity(context, "AdProxiedUser"); 
      var t = UserProxyPrincipal.FindByIdentity(context, "AdamUser"); 
      Console.WriteLine("User AdProxiedUser is {0}" ,p != null ? p.DistinguishedName : "null"); 
      Console.WriteLine("User AdamUser is {0}", t != null ? t.DistinguishedName : "null"); 

     } 
    } 
} 

這是我的輸出和代碼貼:

 
    Log AdamUser : True 
    Log AdProxiedUser : True 
    User AdProxiedUser is CN=AdProxiedUser,OU=Usagers,DC=dev,DC=local 
    User AdamUser is null 

現在,如果我換兩個DirectoryObjectClass我UserProxyPrincipal這樣的:

[DirectoryObjectClass("user")] 
    [DirectoryObjectClass("userProxy")] 

我有這樣的結果(交換結果):

 
    Log AdamUser : True 
    Log AdProxiedUser : True 
    User AdProxiedUser is null 
    User AdamUser is CN=AdamUser,OU=AdamUsers,OU=Usagers,DC=dev,DC=local 

看到我可以定義兩個不同的DirectoryObjectClassAttribute,我開始想這可能是我必須設置兩個不同的DirectoryPropertyAttri布特這樣的:

[DirectoryProperty("objectSid")] 
    [DirectoryProperty("objectSid")] 
    public string ObjectSid 
     [...] 

    [DirectoryProperty("name")] 
    [DirectoryProperty("name")] 
    public new string Name 
     [...] 

再次被交換的結果一個得到的(我不停的換DirectoryObjectClassAttribute)

 
    Log AdamUser : True 
    Log AdProxiedUser : True 
    User AdProxiedUser is CN=AdProxiedUser,OU=Usagers,DC=dev,DC=local 
    User AdamUser is null 

希望將有助於瞭解什麼是我的問題

哦,順便說一下,如果我刪除雙重屬性,只保留這一個:

[DirectoryObjectClass("userProxy")] 

而具體使用UserPrincipal我AdamUser(用戶對象類)和我爲我的AdProxiedUser(userProxy對象類)UserProxyPrincipal這樣的:

var p = UserProxyPrincipal.FindByIdentity(context, "AdProxiedUser"); 
var t = UserProxy.FindByIdentity(context, "AdamUser"); 

兩者都匹配。見結果:

 
    Log AdamUser : True 
    Log AdProxiedUser : True 
    User AdProxiedUser is CN=AdProxiedUser,OU=Usagers,DC=dev,DC=local 
    User AdamUser is CN=AdamUser,OU=AdamUsers,OU=Usagers,DC=dev,DC=local 

回答

0

即使這個問題有感覺對我來說,我認爲,答案是不遠處的一個我給Query filter ArgumentException when trying to extending OU principal

問題是活動目錄(和ADAM/LDS)像其他目錄一樣是用類層次結構的概念構建的。因此,您可以使用DirectoryObjectClass在模式分層樹的分支中指定類,但不能在不同分支中使用兩個類。

據我所知,要做你想做的事情,userProxy類必須是你的目錄模式中的用戶類的子類(或相反的順序)。換句話說,您嘗試使用C#構建一個繼承自目錄架構中兩個類(不同分支)的類,並且C#目錄不支持多繼承。

這樣寫,我不回答你的問題,但試圖解釋它爲什麼不起作用。

+0

有趣的一點,我會檢查,看看是否可行,如果是的話,如果它解決了我的問題。 – Groumy 2012-02-17 12:31:10

2

我知道這是前一段時間(2年)發佈。但我介入了一個我想解決的類似問題。我希望有一個從基類「Principal」繼承的「GeneralPrincipal」,以便能夠同時查詢計算機,組和用戶。

首先,我想僅使用(在反射器類System.DirectoryServices.AccountManagement.ExtensionHelper)的DirectoryObjectClassAttributes之一:

internal static string ReadStructuralObjectClass(Type principalType) 
{ 
    DirectoryObjectClassAttribute[] attributeArray = (DirectoryObjectClassAttribute[]) Attribute.GetCustomAttributes(principalType, typeof(DirectoryObjectClassAttribute), false); 
    if (attributeArray == null) 
    { 
     return null; 
    } 
    string objectClass = null; 
    for (int i = 0; i < attributeArray.Length; i++) 
    { 
     if (!attributeArray[i].Context.HasValue && (objectClass == null)) 
     { 
      objectClass = attributeArray[i].ObjectClass; 
     } 
    } 
    return objectClass; 
} 

我如何解決它:

我 「上當」 的讀者通過做這樣的屬性(看看DirectoryObjectClassAttribute):

[DirectoryRdnPrefix("CN")] 
[DirectoryObjectClass("*)(|(objectClass=computer)(objectClass=group)(objectClass=user)")] 
public class GeneralPrincipal : Principal 
{ 
    private static readonly FieldInfo _unpersistedField = typeof(Principal).GetField("unpersisted", BindingFlags.Instance | BindingFlags.NonPublic); 

    #region Constructors 

    public GeneralPrincipal(PrincipalContext context) 
    { 
     if(context == null) 
      throw new ArgumentNullException("context"); 

     this.ContextRaw = context; 
     _unpersistedField.SetValue(this, true); 
    } 

    #endregion 
} 

希望這有助於有人

問候漢斯

+0

Kinderg,'[DirectoryObjectClass(「*)(|(objectClass = computer)(objectClass = group)(objectClass = user)」)]'這節省了我太多的時間!謝謝。 – smr5 2015-07-28 19:46:34