12

私はMVC 4イントラネットアプリケーションで作業しており、Windows認証を使用しています。認証メソッドが使用するユーザーオブジェクトに@User)を追加し、アクティブなディレクトリ(電子メール、電話番号など)からそのデータを取得したいと思います。MVC 4のWindows認証でActive Directoryユーザー情報を取得

カスタムのAuthorize属性を作成し、他のすべてのコントローラが継承するコントローラに追加することができますが、これが適切な方法であるかどうかわかりません。

私の最終目標は簡単ですが、@UserオブジェクトにActive Directory経由で追加されたプロパティを追加します。あなたが提供できるお手伝いをありがとう。

答えて

28

私は自分の質問をStackOverflowに追加しようとしていましたが、あなたの既存の質問を見たときにこの問題を他の人に助けるための私の解決策がありました。これは非常に一般的なことだと思われますが、それを行う方法に関する情報は複数のソースの間に広がっており、追跡するのは難しいです。完全なリソースは1つだけではありませんので、これがあなたと他の人を助けてくれるでしょう。

これを行う最善の方法は、UserPrincipal拡張を使用することです。基本的には、UserPrincipalをサブクラス化してSystem.DirectoryServices.AccountManagementから独自のプロパティを追加しています。これはExtensionGetExtensionSet(やや魔法のような)方法で有効になります。

[DirectoryRdnPrefix("CN")] 
[DirectoryObjectClass("user")] 
public class UserPrincipalExtended : UserPrincipal 
{ 
    public UserPrincipalExtended(PrincipalContext context) : base(context) 
    { 
    } 

    public UserPrincipalExtended(PrincipalContext context, string samAccountName, string password, bool enabled) 
     : base(context, samAccountName, password, enabled) 
    { 
    } 

    [DirectoryProperty("title")] 
    public string Title 
    { 
     get 
     { 
      if (ExtensionGet("title").Length != 1) 
       return null; 

      return (string)ExtensionGet("title")[0]; 
     } 

     set 
     { 
      ExtensionSet("title", value); 
     } 
    } 

    [DirectoryProperty("department")] 
    public string Department 
    { 
     get 
     { 
      if (ExtensionGet("department").Length != 1) 
       return null; 

      return (string)ExtensionGet("department")[0]; 
     } 

     set 
     { 
      ExtensionSet("department", value); 
     } 
    } 

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

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

クラスの2つの属性は、広告のインスタンスに合わせてカスタマイズする必要があります。 DirectoryRdnPrefixの値は、ADのRDN(相対識別名)である必要がありますが、DirectoryObjectClassの値はuserObjectクラスのADのディレクトリオブジェクトタイプ名である必要があります。一般的なADドメインサービスのセットアップでは、上記のコードで両方を使用する必要がありますが、LDSの設定ではと異なる場合があります。私は自分の組織が使用する2つの新しいプロパティ、 "title"と "department"を追加しました。それで、あなたが好きな他のプロパティを追加する方法を知ることができます:基本的にはここで提供したテンプレートを使ってプロパティを作成するだけです。このプロパティの名前は任意ですが、DirectoryPropertyに渡されたコードブロック内の文字列値は、ADのプロパティ名と一致する必要があります。これで、UserPrincipalではなく、サブクラスでPrincipalContextを使用して、追加する必要があるプロパティを持つユーザーオブジェクトを取得できます。

UserPrincipalExtended user = UserPrincipalExtended.FindByIdentity(
    new PrincipalContext(ContextType.Domain), User.Identity.Name); 

そしてUserPrincipalインスタンス上の他のようなあなたのプロパティにアクセス:

// User's title 
user.Title 

あなたはSystem.DirectoryServices.AccountManagement.UserPrincipalに慣れていない方は、焼き少数のユーザープロパティがあります:などGivenNameSurnameDisplayNameは、具体的には、電話やメールに具体的に言及したので、VoiceTelephoneNumberEmailAddressがあります。 MSDN docsに完全なリストが表示されます。あなたが必要とする情報がすべてビルトイン情報であれば、上に示したようにUserPrincipalを拡張する必要はありません。あなただけだろう:それは簡単に残りの部分を取得する方法を知って良いことだので

UserPrincipal user = UserPrincipal.FindByIdentity(
    new PrincipalContext(ContextType.Domain), User.Identity.Name); 

しかし、10のうち9回、組み込み関数は、十分ではありません。

最後に、これを使用するビューに@using行を追加したくないので、先に進み、Viewsフォルダのweb.configに名前空間を追加しました。その部分は重要ですが、Viewsフォルダのweb.configに追加する必要があります。プロジェクトのものではありません(エリアを利用している場合は、各エリアのViewsフォルダ)。

<system.web.webPages.razor> 
    ... 
    <pages pageBaseType="System.Web.Mvc.WebViewPage"> 
     <namespaces> 
      ... 
      <add namespace="System.DirectoryServices.AccountManagement" /> 
      <add namespace="Namespace.For.Your.Extension" /> 
     </namespaces> 
    </pages> 
</system.web.webPages.razor> 
+0

を見つけるか、または追加することはできません

私はこの拡張機能を好きですが、私はのUserPrincipalクラスの経験を持っていません。 UserPrincipal Typesをこの新しいクラスに置き換えましたが、静的なFindByIdentityメソッドを呼び出すときにエラーが発生しました。追加情報:UserPrincipalExtendedタイプのプリンシパルオブジェクトは、このストアに対するクエリでは使用できません。なぜそれが失敗するかについてのアイデア? –

-1
[DirectoryRdnPrefix("CN")] 
[DirectoryObjectClass("user")] 

これらは認識されていません。あなたはあなたのmvc 4剃刀プロジェクトでコントロールを作成しましたか?私も参照System.DirectoryServices.AccountManagement

関連する問題