在 MVC 4 中使用 Windows 身份验证获取 Active Directory 用户信息 [英] Get Active Directory User Information With Windows Authentication in MVC 4

查看:25
本文介绍了在 MVC 4 中使用 Windows 身份验证获取 Active Directory 用户信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发 MVC 4 Intranet 应用程序并使用 Windows 身份验证.我想添加到身份验证方法使用的用户对象 (@User) 并从活动目录中获取该数据(例如电子邮件、电话号码等).

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

我知道我可以创建一个自定义 Authorize 属性并将其添加到我的所有其他控制器都继承自的控制器中,但我不知道这是否是我想要的正确方法.

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.

推荐答案

当我看到您现有的问题时,我正准备将我自己的问题和我的解决方案添加到 StackOverflow 以帮助其他人解决这个问题.看起来这将是一件非常普遍的事情,但有关如何执行此操作的信息仅分布在多个来源之间并且难以追踪.不只有一种完整的资源,所以希望这对您和其他人有所帮助.

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 扩展.基本上,您是从 System.DirectoryServices.AccountManagement 继承 UserPrincipal 并添加您自己的附加属性.这是通过 ExtensionGetExtensionSet(有点神奇的)方法启用的.

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

类上的两个属性需要根据您的 AD 实例进行自定义.DirectoryRdnPrefix 的值需要是 AD 中的 RDN(相对专有名称),而 DirectoryObjectClass 的值需要是 AD 中 userObject 类的目录对象类型名称.对于典型的 AD 域服务设置,它们应该与上面提供的代码中使用的一样,但对于 LDS 设置,它们可能不同.我添加了我的组织使用的两个新属性,title"和department".从中,您可以了解如何添加您喜欢的任何其他属性:基本上,您只需使用我在此处提供的模板创建一个属性.该属性可以任意命名,但传递给 DirectoryProperty 和代码块内的字符串值应与 AD 中的属性名称匹配.有了它,您可以将 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 不熟悉,那么有一些用户属性已被烘焙:GivenNameSurnameDisplayName 等.特别是针对您的情况,因为您专门提到了电话和电子邮件,所以有 VoiceTelephoneNumberEmailAddress.您可以在 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);

但是,10 次中有 9 次,内置函数是不够的,所以知道如何轻松获得其余部分是很好的.

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 行,所以我继续将命名空间添加到我的 Views 文件夹的网络配置.这部分很重要,它需要添加到 Views 文件夹的 web.config 中,而不是项目的(如果使用区域,则是每个区域的单独 Views 文件夹).

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>

这篇关于在 MVC 4 中使用 Windows 身份验证获取 Active Directory 用户信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆