如何以username@domain格式获取当前Windows用户的名称?

11
我知道以下函数会返回当前Windows用户的域名\用户名格式的名称。
Convert.ToString( WindowsIdentity.GetCurrent().Name );

但是我如何以 username@domain 的格式获取用户的名称?

编辑:

我在这个编辑中回复,因为回答我的每个人都有相同的基本想法。

据我所了解,从 domain\username 格式中解析名称并构造为 username@domain 不安全也不建议这样做。我认为这是因为不能保证两个域名在不同的格式中相同。例如,在我工作的公司中,domain\username 格式的 domain 部分基于部门,但在 username@domain 中,它是公司名称。这是一种需要进行 DNS 查找的情况。

我希望有一个可以进行这种 DNS 查找的 API。我想我应该把这些信息放到我的原始问题中。对不起。


我在我的应用程序中使用C#。 - Tony Vitabile
你要查找的属性是用户主体名称(UPN)。 - Harry Johnston
1
尝试枚举WindowsIdentity.GetCurrent().Claims,可能会包含UPN。如果没有,请使用P/Invoke调用TranslateName函数。 - Harry Johnston
我找不到WindowsIdentity.GetCurrent().Claims属性。 - Tony Vitabile
@TonyVitabile 你可以尝试使用 WindowsIdentity.GetCurrent().Name - Cullub
你可以尝试使用 Environment.UserDomainNameEnvironment.UserName - Pavel Cermak
7个回答

13

这样的代码应该可以正常工作...

string[] temp = Convert.ToString(WindowsIdentity.GetCurrent().Name).Split('\\');
string userName = temp[1] + "@" + temp[0];

5
所有用于解析以Domain\user name格式输入的用户名的代码并不能在所有情况下起作用。答案是需要调用Active Directory来获取用户主体名称。实际上,我不能依赖于桌面上安装了Active Directory,因为许多警察局不会在他们的笔记本电脑上安装该目录,以防止警察不在车内时被盗。(谈论勇气,竟然从警车里偷电脑!)
我们为我们的情况想出了自己的解决方案。我们将用户名称以Domain\user name格式存储在我们的数据库中。当程序启动时,它会检查当前Windows用户名(以相同的格式)是否在数据库中。如果是,程序将使用该用户作为当前用户并运行。如果当前Windows用户不在我们的数据库中,程序将退回到我们以前的代码。
这样,用户可以使用任何格式的用户名登录机器,并通过Windows进行身份验证。我们的程序始终以相同的格式获取用户名,并始终检查该格式的用户名。Windows对用户进行身份验证,而不是我们。

1
就记录而言,Active Directory是服务器组件,因此永远不会“安装在桌面上”。可能的问题是您无法依赖于与域控制器的网络连接。 - Harry Johnston
是的,那完全正确。笔记本电脑在警车里。并非所有这些笔记本电脑都具有在路上使用的任何类型的连接性,而那些具有连接性的可能也不可靠。 - Tony Vitabile
所以你的意思基本上是:“出于安全原因,警察局不想在本地存储用户名,但为了让我的程序能够工作,我忽视了这一要求”? - StoriKnow
不,那并不正确。正如已经指出的那样,活动目录在服务器上作为服务运行。计算机安装在车辆中,可能无法可靠地连接到活动目录服务器,即使它安装了蜂窝卡。我只有一个可以访问应用程序的用户列表。我不知道他们的密码甚至不知道他们的电子邮件地址,只知道他们的用户名和权限。这是确保用户登录到计算机上可以访问任何内容的唯一方法。 - Tony Vitabile

4
使用
System.DirectoryServices.AccountManagement.UserPrincipal.Current.UserPrincipalName

此代码返回当前用户的UPN。需要引用System.DirectoryServices.AccountManagement。


4
您可以使用 \ 作为分隔符来拆分名称,然后像这样反转顺序:
string[] splitName = WindowsIdentity.GetCurrent().Name.Split('\\');
//check that splitName contains at least 2 values before using
string name = (splitName.Length > 1) ? splitName[1] + "@" + splitName[0] : null;

需要注意的是,双反斜杠\\是必需的,因为反斜杠是一个特殊字符。在上面的例子中,我们添加第二个反斜杠来转义特殊字符并将其用作普通字符。


抱歉重复回答 - 显然你和我同时在输入。 - Kevin
没关系,@Kevin。虽然我不得不添加条件检查来尝试超越你 :-P。 - StoriKnow

4
var input =  WindowsIdentity.GetCurrent().Name ;
string[] tab = input.Split('\\');
var result = tab[1] + "@" +  tab[0];

你使用了两次tab[1],这将返回username@username。 - StoriKnow
@StoriKnow - 不,它返回“用户名@域名”。 - Matt

0

我看过很多同样的变量,为什么不将它们放入一个函数中:

string GetUserName()
{
    var currentName =  WindowsIdentity.GetCurrent()?.Name;
    if (string.IsNullOrEmpty(currentName)) return null;
    var nameSplit = currentName.Split(@"\");
    string name = (nameSplit.Length > 1)
                    ? $"{nameSplit[1]}@{nameSplit[0]}" : currentName;
    return name;
}

currentName 什么时候会返回 null 值? - el-musleh
通常情况下不会发生,但如果函数无法获取名称,则可能会发生。然后GetUserName()函数不会中断,而是返回null。 - Matt

0

大致上是这样的。

var nameParts = WindowsIdentity.GetCurrent().Name.Split(@"\");
string name = nameParts.Length == 1 
    ? nameParts  
    : string.format("{0}@{1}",nameParts[1],nameParts[0]);

你的代码格式乱了。另外,为什么你的代码假设 nameParts.Length == 1 表示一个数组的安全使用,而这个数组应该至少有(可能不超过)2个元素。根据你的假设,检查 UpperBound 可能更合适,像这样 (nameParts.GetUpperBound(0) == 1) - StoriKnow
你的代码无法编译。你不能将字符串数组nameParts赋值给一个字符串。另外,string.format不存在,应该是string.Format。最后,Split(@"\")不可能实现,因为Split不接受字符串(但它可以接受字符串数组)。 - StoriKnow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接