获取的Active Directory用户信息使用Windows身份验证MVC 4用户信息、身份验证、Directory、Active

由网友(一抹极端的笑)分享简介:我工作的一个MVC 4 Intranet应用程序和正在使用Windows身份验证。我想补充到,该认证方法使用(@user)的用户对象,并从Active Directory中的数据(如电子邮件,电话号码等)。 I am working on an MVC 4 intranet application and am us...

我工作的一个MVC 4 Intranet应用程序和正在使用Windows身份验证。我想补充到,该认证方法使用(@user)的用户对象,并从Active Directory中的数据(如电子邮件,电话号码等)。

I am working on an MVC 4 intranet application and am using Windows authentication. I would like to add to the user object that the authentication method uses (@User) and get that data from active directory (such as email, phone number, etc).

我知道我可以创建自定义授权属性并将其添加到我所有的其他控制器从继承的控制器,但我不知道这是否是正确的方法做我想要的。

I know I can create a custom Authorize attribute and add it to the controller that all of my other controllers inherit from, but I don't know if this is the right method to do what I want.

我的最终目标很简单,我想@user对象有通过Active Directory中填充额外的属性。感谢您的帮助,您可以提供。

My end goal is simple, I want @User object to have additional properties that are populated via Active Directory. Thanks for any help you can offer.

推荐答案

我正要加入我自己的问题与我的解决方案,以计算器帮助别人这个问题,当我看到您现有的问题。看起来这将是一个很平常的事情,但如何做到这一点,该信息只为S $ P $垫了多个来源和难以追查之间。有不只是一个完整的资源,所以希望这将帮助您和他人。

I was just about to add my own question to StackOverflow with my solution to help others with this issue, when I saw your existing question. It seems like this would be a very common thing, but the information about how to do it only is spread out between multiple sources and hard to track down. There's not just one complete resource, so hopefully this will help you and others.

要做到这一点,最好的方法是使用一个UserPrincipal扩展。基本上,你继承 UserPrincipal System.DirectoryServices.AccountManagement 并添加你自己的附加属性。这是通过启用 ExtensionGet ExtensionSet (有点不可思议)的方法。

The best way to do this is use a UserPrincipal extension. Basically, you're subclassing UserPrincipal from System.DirectoryServices.AccountManagement and adding your own additional properties. This is enabled via the ExtensionGet and ExtensionSet (somewhat magical) methods.

[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);
    } 
}

在类中的两个属性需要进行定制,以广告的实例。该值 DirectoryRdn preFIX 需要是RDN(相对专有名称)于公元,而 DirectoryObjectClass 需要在公元一userObject类的目录对象类型名称。对于典型的AD域服务的设置,他们都应该是在上述psented的code $ P $使用,但是对于一个LDS安装,它们的可以的不同。我又说,我的组织使用,标题和部门两个新的属性。从这一点,你可以得到如何添加任何你喜欢的其他财产的想法:基本上你刚才创建使用我在这里提供的模板的属性。该属性可以被命名为任何你喜欢的,但是字符串值传递给 DirectoryProperty 和code座里面应该匹配到一个属性名从公元。随着在地方,你可以使用 PrincipalContext 与你的子类,而不是 UserPrincipal 返回与属性的用户对象你需要添加。

The two attributes on the class need to be customized to your instance of AD. The value for DirectoryRdnPrefix needs to be the RDN (relative distinguished name) in AD, while the value for DirectoryObjectClass needs to be the directory object type name in AD for a userObject class. For a typical AD Domain Services setup, they should both be as used in the code presented above, but for an LDS setup, they could be different. I've added two new properties that my organization uses, "title" and "department". From that, you can get an idea of how to add any other property you like: basically you just create a property using the template I've provided here. The property can be named anything you like, but the string value passed to DirectoryProperty and inside the code block should match up to a property name from AD. With that in place, you can use PrincipalContext with your subclass instead of UserPrincipal to get back a user object with the properties you need added.

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

和访问你的财产像任何其他关于 UserPrincipal 例如:

And access your property like any other on the UserPrincipal instance:

// User's title
user.Title

如果您不熟悉 System.DirectoryServices.AccountManagement.UserPrincipal ,还有烤了​​几个用户属性: GivenName上显示名称等。尤其是你的情况,因为你特别提到的电话和电子邮件,还有 VoiceTelephoneNumber EmailAddress的。你可以看到完整的列表中的MSDN文档。如果你需要的是内置的信息,你不需要延长 UserPrincipal 我上面显示。你会只是做:

If you're unfamiliar with System.DirectoryServices.AccountManagement.UserPrincipal, there's a few user properties baked in: GivenName, Surname, DisplayName, etc. In particular to your circumstance, since you mentioned phone and email specifically, there's VoiceTelephoneNumber and EmailAddress. You can see the full list in the MSDN docs. If all you need is the built-in information, you don't need to extend UserPrincipal as I showed above. You would just do:

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

不过,9次了10年,内置插件是不够的,所以它的好,知道如何轻松地得到休息。

But, 9 times out of 10, the built-ins won't be enough, so it's good to know how to get the rest easily.

最后,我不希望有添加 @using 行使用此的任何观点,让我继续,并添加了命名空间,以我的浏览文件夹中的web.config。这部分是很重要的,它需要被添加到浏览文件夹中的web.config文件,不是项目的(各地区的个性化浏览如果你使用区域文件夹)。

Finally, I didn't want to have to add @using lines to any view that uses this, so I went ahead and added the namespaces to my Views folder's web.config. That part is important, it needs to be added to the Views folder's web.config, not the project's (and each Area's individual Views folder if you're utilizing Areas).

<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>