English 中文(简体)
我怎样在C#中将一个SID转换为账户名?
原标题:
  • 时间:2009-01-31 15:56:52
  •  标签:

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

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

然而,这对于网络上的文件不起作用,可能是因为Translate()函数只能用于本地用户帐户。我想也许我可以对SID进行LDAP查找,所以我尝试了以下内容:

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

这似乎会起作用,因为“dirEntry.Name”的访问会挂起几秒钟,就好像正在离线查询网络一样,但接着会抛出System.Runtime.InteropServices.COMException。

有人知道我如何获取任意文件或SID的帐户名吗?我对网络或LDAP或任何事情都不是很了解。有一个叫做DirectorySearcher的类,也许我应该使用它,但它需要一个域名,而我也不知道如何获取 - 我拥有的只是我正在扫描的目录的路径。

最佳回答

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转换为用户对象。它应该能够在本地机器或LDAP / Active Directory服务器上运行。 我只在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.

在C#中,通过以下方式获取用户SID并将其赋值给字符串变量:

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

您需要使用字符串,因为解析到UserName支持字符串。换句话说,使用var varUser会导致命名空间错误。

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

您还可以通过以下类似的代码获取特殊账户(如“Everyone”)的账户名,这将不受用户语言设置的影响:

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

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

你真的应该检查你的机器是否是Active Directory的一部分。你可以在登录过程中了解到这一点。或者你可以右键点击“My Computer”,选择“属性”,然后选择“计算机名”选项卡,看看你的计算机是否属于一个域。

太好了。我从这里抄了一些LookupAccountSid()代码:

将此翻译成中文:http://www.pinvoke.net/default.aspx/advapi32.LookupAccountSid http://www.pinvoke.net/default.aspx/advapi32.LookupAccountSid

这很有效,尽管我不得不自己提供主机名。对于UNC路径,我只需取其第一个组件。当它是映射驱动器时,我使用这段代码将路径转换为UNC:

将此翻译为中文:http://www.wiredprairie.us/blog/index.php/archives/22

看起来可以工作,所以除非有人提出一种情况,在这种情况下UNC路径的第一个组件不是主机名...否则我会这样做。

谢谢大家的帮助。

这是个难题。你在Active Directory环境下,对吗?只是确认一下 :)

无论如何,不要绑定sid.Value,

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

我会尝试将 SID 的字节数组转换为并绑定。

这里有一个甜蜜的例子,位于第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));

在激活目录中使用域目录条目和用户名完成目录搜索。

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/>";
                }
            }
        }

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

这里有一个网站,它包含我需要的所有用户属性:http://www.winzero.ca/Active-Directory-users.htm。

对于所有的Windows开发人员,答案是LookupAccountSid。

LookupAccountSid(null, Sid, username, userSize, domainName, domainSize, sidType);




相关问题
热门标签