【问题标题】:Get Active Directory User Information With Windows Authentication in MVC 4在 MVC 4 中使用 Windows 身份验证获取 Active Directory 用户信息
【发布时间】:2013-12-08 01:04:24
【问题描述】:

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

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

我的最终目标很简单,我希望 @User 对象具有通过 Active Directory 填充的其他属性。感谢您提供的任何帮助。

【问题讨论】:

    标签: asp.net-mvc-4 authentication active-directory windows-authentication


    【解决方案1】:

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

    最好的方法是使用 UserPrincipal 扩展。基本上,您从System.DirectoryServices.AccountManagement 继承UserPrincipal 并添加您自己的附加属性。这是通过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);
        } 
    }
    

    类的两个属性需要根据您的 AD 实例进行定制。 DirectoryRdnPrefix 的值需要是 AD 中的 RDN(相对专有名称),而 DirectoryObjectClass 的值需要是 AD 中 userObject 类的目录对象类型名称。对于典型的 AD 域服务设置,它们都应该与上述代码中使用的一样,但对于 LDS 设置,它们可能不同。我添加了我的组织使用的两个新属性,“title”和“department”。由此,您可以了解如何添加您喜欢的任何其他属性:基本上您只需使用我在此处提供的模板创建一个属性。该属性可以任意命名,但传递给DirectoryProperty 和代码块内部的字符串值应与AD 中的属性名称匹配。有了它,您可以将PrincipalContext 与您的子类一起使用而不是UserPrincipal 来取回具有您需要添加的属性的用户对象。

    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>
    

    【讨论】:

    • 我喜欢这个扩展,但我没有使用 userprincipal 类的经验。我用这个新类替换了我的 UserPrincipal 类型,但在调用静态 FindByIdentity 方法时出错。附加信息:UserPrincipalExtended 类型的主体对象不能用于针对此存储的查询。关于它为什么失败的任何想法?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-19
    • 1970-01-01
    相关资源
    最近更新 更多