Pergunta

Eu tenho um aplicativo C # que examina um diretório e reúne algumas informações. Gostaria de exibir o nome da conta para cada arquivo. Eu posso fazer isso no sistema local por obter o SID para o objeto FileInfo, e depois fazer:

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

No entanto, isso não funciona para arquivos em uma rede, presumivelmente porque a função Translate () só funciona com contas de usuários locais. Eu pensei que talvez eu poderia fazer uma pesquisa LDAP na SID, então eu tentei o seguinte:

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

Isto parece que vai funcionar, em que o acesso a trava "dirEntry.Name" por alguns segundos, como se está a sair e consultar a rede, mas, em seguida, ele lança um System.Runtime.InteropServices.COMException

Alguém sabe como posso obter o nome da conta de um arquivo arbitrário ou SID? Eu não sei muito sobre a rede ou LDAP ou qualquer coisa. Há uma classe chamada DirectorySearcher que talvez eu deveria usar, mas quer um nome de domínio, e eu não sei como conseguir que quer - tudo que eu tenho é o caminho para o diretório que eu sou digitalização

Agradecemos antecipadamente.

Foi útil?

Solução

método Traduzir do objeto SecurityReference funciona no SID não-locais, mas apenas para contas de domínio. Para contas locais para outra máquina ou em uma configuração de domínio não seria necessário PInvoke a função LookupAccountSid especificando o nome da máquina específica em que o olhar se precisa ser executada.

Outras dicas

Veja aqui uma boa resposta:

A melhor maneira de nome de usuário de exibição determinação por SID?

A essência do que é este bit:

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();

Esta abordagem funciona para mim para SID de não-local sobre o diretório ativo.

classe System.DirectoryServices.AccountManagement.UserPrincipal ( MSDN ligação ) tem uma função estática FindByIdentity para converter um SID para um objeto Usuário. Ele deve ser capaz de trabalhar tanto contra a máquina local ou um servidor de diretório LDAP / Active Directory. Eu só tenho usado isso contra Active Directory.

Aqui está um exemplo que eu usei no 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.

Em C #, obter o SID de usuário e atribuí-la a uma variável de cadeia através de:

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

Você vai precisar de corda uso, porque a capacidade de resolver para o UserName suporta string. Em outras palavras, usando var varUser irá resultar em um erro de namespace.

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

Ooh, então é possível que a chamada LDAP não está funcionando porque você não pode estar em um ambiente Active Directory. Se este for o caso, então cada uma de suas máquinas é responsável pela sua própria loja de identidade. E sua primeira amostra de código não está funcionando em toda a rede, porque a máquina na qual você está executando o código não sabe como resolver o SID que só faz sentido na máquina remota.

Você realmente deve verificar se suas máquinas são uma parte de um Active Directory. Você saberia isso durante o processo de logon. Ou você pode verificar com o botão direito em "Meu Computador", selecione "Propriedades", na aba "Nome do Computador", então veja se o computador fizer parte de um domínio.

Grande. I cribbed algum código LookupAccountSid () a partir daqui:

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

E isso funcionou, mas eu tinha que fornecer o nome do host mim. No caso de um caminho UNC eu só posso dar o primeiro componente do mesmo. Quando ele é uma unidade mapeada, eu uso este código para converter o caminho para um UNC um:

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

Parece que funciona, então é assim que eu vou fazer isso, a menos que alguém surge com uma situação em que o primeiro componente de um caminho UNC não é o nome do host ...

Obrigado a todos por sua ajuda.

Você também pode obter o nome da conta de contas especiais, como "Todos" com um código como este que irão trabalhar independentemente de configurações de idioma do usuário:

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

Este é um stumper. Você está em um certo ambiente do Active Directory? Apenas verificando:)

De qualquer forma, em vez de ligação com sid.Value,

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

Gostaria de tentar converter array de bytes do SID a um octeto de Cordas e ligam-se com que, em vez.

Há um exemplo doce aqui na página 78. Isto fará você mais perto. Para ser honesto, eu não tentei ligação com um SID antes. Mas eu tive de ligação com o GUID de um usuário sucesso embora :)

Boa sorte e deixe-me saber como ele vai.

Obter o domínio atual:

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

Obter uma entrada de diretório do LDAP e o nome de domínio:

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

Obter o sid de um ActiveDirectoryMembershipProvider ActiveDirectoryMembershipUser:

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

Obter o nome de usuário do SecurityIdentifier:

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

Get pesquisa de diretório feito em uma activedirectory com a entrada de diretório de domínio e nome de usuário:

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

Dependendo dos dados em seu diretório ativo, você receberá uma resposta variada na saída.

Aqui está um site que tem todas as propriedades de usuário que eu precisava:

Estou bastante certeza que você vai ser capaz de usar a resposta aceita a partir daqui: Determine o nome da conta LocalSystem usando C #

Basicamente, você pode traduzir uma instância da classe SecurityIdentifier para digitar NTAccount, a partir do qual você pode obter o nome de usuário. No código:

using System.Security.Principal;

SecurityIdentifier sid = new SecurityIdentifier("S-1-5-18");
NTAccount acct = (NTAccount)sid.Translate(typeof(NTAccount));
Console.WriteLine(acct.Value);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top