如何在C#中将SID转换为帐户名称

我有一个C#应用程序,它扫描一个目录并收集一些信息。 我想显示每个文件的帐户名称。 我可以通过获取FileInfo对象的SID在本地系统上执行此操作,然后执行以下操作:

string GetNameFromSID( SecurityIdentifier sid ) { NTAccount ntAccount = (NTAccount)sid.Translate( typeof( NTAccount ) ); return ntAccount.ToString(); } 

但是,这对networking上的文件不起作用,大概是因为Translate()函数只能用于本地用户帐户。 我想也许我可以在SID上进行LDAP查找,所以我尝试了以下方法:

 string GetNameFromSID( SecurityIdentifier sid ) { string str = "LDAP://<SID=" + sid.Value + ">"; DirectoryEntry dirEntry = new DirectoryEntry( str ); return dirEntry.Name; } 

这似乎是可行的,因为对“dirEntry.Name”的访问会挂起几秒钟,好像它正在closures并查询networking,但是它会抛出一个System.Runtime.InteropServices.COMException

有谁知道我可以如何获得任意文件或SID的帐户名称? 我不太了解networking或LDAP或任何东西。 有一个名为DirectorySearcher的类,也许我应该使用,但它想要一个域名,我不知道如何得到这一点 – 我所有的是我正在扫描的目录的path。

提前致谢。

SecurityReference对象的Translate方法在非本地SID上工作,但仅适用于域帐户。 对于另一台机器本地帐户或非域设置帐户,您将需要PInvoke函数LookupAccountSid指定查询需要执行的特定机器名称。

在这里看到一个很好的答案:

通过SID解决显示用户名的最佳方法是什么?

它的要点是这样的:

 string sid="S-1-5-21-789336058-507921405-854245398-9938"; string account = new System.Security.Principal.SecurityIdentifier(sid).Translate(typeof(System.Security.Principal.NTAccount)).ToString(); 

这种方法适用于非活动目录中的非本地SID。

System.DirectoryServices.AccountManagement.UserPrincipal类( msdn链接 )有一个静态函数FindByIdentity将SID转换为User对象。 它应该能够在本地机器或LDAP / Active Directory服务器上工作。 我只用它对活动目录。

这里是我在IIS中使用的一个例子:

 // Set the search context to a specific domain in active directory var searchContext = new PrincipalContext(ContextType.Domain, "YOURDOMAIN", "OU=SomeOU,DC=YourCompany,DC=com"); // get the currently logged in user from IIS MembershipUser aspUser = Membership.GetUser(); // get the SID of the user (stored in the SecurityIdentifier class) var sid = aspUser.ProviderUserKey as System.Security.Principal.SecurityIdentifier; // get the ActiveDirectory user object using the SID (sid.Value returns the SID in string form) var adUser = UserPrincipal.FindByIdentity(searchContext, IdentityType.Sid, sid.Value); // do stuff to user, look up group membership, etc. 

哦,那么有可能LDAP调用不起作用,因为你可能不在Active Directory环境中。 如果是这种情况,那么你的每台机器都要负责自己的身份存储。 而且你的第一个代码示例不能在networking上工作,因为执行代码的机器不知道如何parsing只在远程机器上有意义的SID。

你真的应该检查你的机器是否是Active Directory的一部分。 你会在login过程中知道这一点。 或者您可以通过右键单击“我的电脑”进行检查,select“属性”,“计算机名称”选项卡,然后查看您的计算机是否为域的一部分。

大。 我从这里拆了一些LookupAccountSid()代码:

http://www.pinvoke.net/default.aspx/advapi32.LookupAccountSid

这工作,但我必须提供自己的主机名称。 在UNCpath的情况下,我可以把它的第一个组件。 当它是映射驱动器时,我使用此代码将path转换为UNCpath:

http://www.wiredprairie.us/blog/index.php/archives/22

这似乎工作,所以这就是我将如何做,除非有人提出的情况下,UNCpath的第一个组件不是主机名…

感谢大家的帮助。

您还可以像这样的代码获得像“每个人”这样的特殊账户的账户名称,无论用户的语言设置如何,都可以工作:

  SecurityIdentifier everyoneSid = new SecurityIdentifier(WellKnownSidType.WorldSid, null); string everyone = everyoneSid.Translate(typeof(System.Security.Principal.NTAccount)).ToString(); 

在C#中,获取用户SID并通过以下方式将其分配给一个stringvariables:

 string strUser = System.Security.Principal.WindowsIdentity.GetCurrent().User.ToString(); 

您将需要使用string,因为parsing到UserName的能力支持string。 换句话说,使用var varUser将导致命名空间错误。

 string strUserName = new System.Security.Principal.SecurityIdentifier(strUser).Translate(typeof(System.Security.Principal.NTAccount)).ToString(); 

这是一个惊人的。 你是在Active Directory环境中吗? 只是检查:)

无论如何,而不是绑定与sid.Value,

 string str = "LDAP://<SID=" + sid.Value + ">"; 

我会尝试将SID的字节数组转换为八位字节string,并与之绑定。

第78页有一个很好的例子。这会让你更接近。 说实话,我还没有尝试绑定与SID之前。 但我已经成功绑定用户的GUID 🙂

祝你好运,让我知道如何去。

获取当前的域名:

 System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain(); 

从ldap和域名获取一个目录条目:

 DirectoryEntry de = new DirectoryEntry(string.Format("LDAP://{0}", domain)); 

从ActiveDirectoryMembershipProvider ActiveDirectoryMembershipUser获取sid:

 ActiveDirectoryMembershipUser user = (ActiveDirectoryMembershipUser)Membership.GetUser(); var sid = (SecurityIdentifier)user.ProviderUserKey; 

从SecurityIdentifier获取用户名:

 (NTAccount)sid.Translate(typeof(NTAccount)); 

在具有域目录条目和用户名的活动目录上完成目录search:

 DirectorySearcher search = new DirectorySearcher(entry); search.Filter = string.Format("(SAMAccountName={0})", username); search.PropertiesToLoad.Add("Name"); search.PropertiesToLoad.Add("displayName"); search.PropertiesToLoad.Add("company"); search.PropertiesToLoad.Add("homePhone"); search.PropertiesToLoad.Add("mail"); search.PropertiesToLoad.Add("givenName"); search.PropertiesToLoad.Add("lastLogon"); search.PropertiesToLoad.Add("userPrincipalName"); search.PropertiesToLoad.Add("st"); search.PropertiesToLoad.Add("sn"); search.PropertiesToLoad.Add("telephoneNumber"); search.PropertiesToLoad.Add("postalCode"); SearchResult result = search.FindOne(); if (result != null) { foreach (string key in result.Properties.PropertyNames) { // Each property contains a collection of its own // that may contain multiple values foreach (Object propValue in result.Properties[key]) { outputString += key + " = " + propValue + ".<br/>"; } } } 

根据活动目录中的数据,您将在输出中得到不同的响应。

这里是一个网站,有我需要的所有用户属性:

我相当肯定,你将能够使用从这里接受的答案: 确定LocalSystem帐户名称使用C#

基本上,您可以将SecurityIdentifier类的实例转换为NTAccounttypes,从中可以获取用户名。 在代码中:

 using System.Security.Principal; SecurityIdentifier sid = new SecurityIdentifier("S-1-5-18"); NTAccount acct = (NTAccount)sid.Translate(typeof(NTAccount)); Console.WriteLine(acct.Value);