当我看到您现有的问题时,我正要使用我的解决方案将我自己的问题添加到 StackOverflow 以帮助其他人解决此问题。看起来这将是一件非常普遍的事情,但是有关如何执行此操作的信息仅分布在多个来源之间并且难以追踪。不只是一个完整的资源,所以希望这会对您和其他人有所帮助。
最好的方法是使用 UserPrincipal 扩展。基本上,您从System.DirectoryServices.AccountManagement 继承UserPrincipal 并添加您自己的附加属性。这是通过ExtensionGet 和ExtensionSet(有点神奇)方法启用的。
[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 不熟悉,这里有一些用户属性:GivenName、Surname、DisplayName 等。特别是针对您的情况,因为您特别提到了电话和电子邮件,所以有VoiceTelephoneNumber 和 EmailAddress。您可以在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>