You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用UserPrincipal::Current获取AD用户DisplayName普通用户失败问题排查

解决Active Directory中普通域用户无法通过UserPrincipal.Current获取DisplayName的问题

问题背景

基于.NET 6的软件调用[System.DirectoryServices.AccountManagement.UserPrincipal]::Current获取当前用户DisplayName时,域管理员账号可正常运行,但普通域用户执行会抛出COMException,错误信息为“指定的目录服务属性或值不存在”。全新搭建的域环境中所有用户均可正常使用该方法,但现有域无法重建,需排查解决。

测试情况

  1. 普通用户执行以下PowerShell命令可正常获取DisplayName:
Import-Module ActiveDirectory
$user = Get-ADUser -Identity "deinBenutzername" -Properties DisplayName
$user.DisplayName
  1. 普通用户执行以下代码时触发错误:
Add-Type -AssemblyName "System.DirectoryServices.AccountManagement"
$context = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Domain)
$userPrincipal = [System.DirectoryServices.AccountManagement.UserPrincipal]::Current
$displayName = $userPrincipal.DisplayName

已尝试但无效的方案

  • 为测试用户添加SELF的完全访问权限
  • 为用户账号自身添加完全访问权限
  • 赋予读取所有AD用户/属性的权限

可能原因分析

  1. UserPrincipal.Current的查询逻辑差异:该方法内部封装的LDAP查询和Get-ADUser不同,可能默认查询全局编录(GC)而非域控制器,或者尝试读取管理员有权限但普通用户无权访问的附加属性,导致整体查询失败。
  2. 域环境权限异常:现有域可能存在权限继承中断,或者displayName属性的读取权限被意外限制,新域默认权限配置正常所以无此问题。
  3. 延迟加载触发的多属性查询:UserPrincipal采用延迟加载,访问DisplayName时会一次性查询多个关联属性,若其中某个属性普通用户无权读取,就会抛出整体错误,而非DisplayName本身权限问题。

解决思路

1. 改用DirectoryServices直接查询(绕过UserPrincipal封装)

既然Get-ADUser能正常获取,可直接用DirectoryServices组件查询当前用户的LDAP条目,精准指定只读取displayName属性:

.NET 6代码示例

using System.DirectoryServices;
using System;

public static string GetCurrentUserDisplayName()
{
    string domain = Environment.UserDomainName;
    string username = Environment.UserName;
    
    using (var entry = new DirectoryEntry($"LDAP://{domain}"))
    using (var searcher = new DirectorySearcher(entry))
    {
        searcher.Filter = $"(&(objectClass=user)(sAMAccountName={username}))";
        searcher.PropertiesToLoad.Add("displayName");
        
        var searchResult = searcher.FindOne();
        return searchResult?.Properties["displayName"]?[0]?.ToString() ?? string.Empty;
    }
}

PowerShell测试代码

$domain = [System.Environment]::UserDomainName
$username = [System.Environment]::UserName

$entry = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$domain")
$searcher = New-Object System.DirectoryServices.DirectorySearcher($entry)
$searcher.Filter = "(&(objectClass=user)(sAMAccountName=$username))"
$searcher.PropertiesToLoad.Add("displayName")

$result = $searcher.FindOne()
$result.Properties["displayName"][0]

2. 检查全局编录(GC)的属性权限

如果UserPrincipal.Current默认查询GC,需确认GC中用户对象的displayName属性对普通用户开放读取权限:

  • 打开AD用户和计算机,启用「查看」→「高级功能」
  • 找到目标用户对象,右键→「属性」→「安全」→「高级」
  • 检查是否存在「Authenticated Users」或用户所在组的读取displayName属性的权限,确保权限继承未被中断

3. 分析LDAP查询日志定位具体问题

在域控制器上启用LDAP查询日志,查看普通用户执行代码时的具体查询请求,定位是哪个属性导致权限不足:

  1. 打开注册表编辑器,导航到HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics
  2. 将「16 LDAP Interface Events」的值设为2(启用详细日志)
  3. 执行报错代码后,打开事件查看器→「应用程序和服务日志」→「目录服务」,查看LDAP查询相关日志,找到失败的属性查询条目

4. 重置用户对象的权限继承

若用户对象的权限继承被中断,尝试恢复默认权限:

  • 打开AD用户和计算机,找到目标用户对象,右键→「属性」→「安全」→「高级」
  • 点击「启用继承」,确认后重新测试代码

内容的提问来源于stack exchange,提问作者katzendrama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 17:31:02