web-dev-qa-db-fra.com

Comment puis-je obtenir le SID du compte Windows actuel?

Je recherche un moyen simple d'obtenir le SID du compte d'utilisateur Windows actuel. Je sais que je peux le faire via WMI, mais je ne veux pas aller dans cette voie.

Toutes mes excuses à tous ceux qui ont répondu en C # pour ne pas avoir spécifié le C++. :-)

29
Franci Penov

Dans Win32, appelez GetTokenInformation , en passant un identificateur de jeton et la constante TokenUser. Il remplira une structure TOKEN_USER pour vous. L'un des éléments est le SID de l'utilisateur. C'est un BLOB (binaire), mais vous pouvez le transformer en chaîne en utilisant ConvertSidToStringSid .

Pour obtenir le descripteur de jeton actuel, utilisez OpenThreadToken ou OpenProcessToken .

Si vous préférez ATL, il contient la classe CAccessToken , qui contient toutes sortes de choses intéressantes.

.NET a la propriété Thread.CurrentPrinciple , qui renvoie une référence IPrincipal. Vous pouvez obtenir le SID:

IPrincipal principal = Thread.CurrentPrincipal;
WindowsIdentity identity = principal.Identity as WindowsIdentity;
if (identity != null)
    Console.WriteLine(identity.User);

Également dans .NET, vous pouvez utiliser WindowsIdentity.GetCurrent (), qui renvoie l'ID utilisateur actuel:

WindowsIdentity identity = WindowsIdentity.GetCurrent();
if (identity != null)
    Console.WriteLine(identity.User);
48
Roger Lipscombe

Cela devrait vous donner ce dont vous avez besoin:

using System.Security.Principal;

...

var sid = WindowsIdentity.GetCurrent (). User;

La propriété User de WindowsIdentity renvoie le SID, par MSDN Docs

7
Jeffrey Meyer
ATL::CAccessToken accessToken;
ATL::CSid currentUserSid;
if (accessToken.GetProcessToken(TOKEN_READ | TOKEN_QUERY) &&
    accessToken.GetUser(&currentUserSid))
    return currentUserSid.Sid();
7
dex black

CodeProject a quelques méthodes différentes que vous pouvez essayer ... Vous n’avez pas mentionné les langues dans lesquelles vous vouliez une solution.

Si vous souhaitez y accéder via un fichier de commandes ou quelque chose, vous pouvez regarder comme PsGetSid par Sysinternals . Il traduit les SID en noms et vice versa.

2
Kevin Fairchild

J'ai trouvé un autre moyen d'obtenir le SID: 

System.Security.Principal.WindowsIdentity id = System.Security.Principal.WindowsIdentity.GetCurrent();
string sid = id.User.AccountDomainSid.ToString();
2
cigar huang

En C #, vous pouvez utiliser soit

using Microsoft.Win32.Security;

...

string username = Environment.UserName + "@" + Environment.GetEnvironmentVariable("USERDNSDOMAIN");

Sid sidUser = new Sid (username);

Ou...

using System.Security.AccessControl;

using System.Security.Principal;

...

WindowsIdentity m_Self = WindowsIdentity.GetCurrent();

SecurityIdentifier m_SID = m_Self.Owner;");

2
silverbugg

Et en code natif:

function GetCurrentUserSid: string;

    hAccessToken: THandle;
    userToken: PTokenUser;
    dwInfoBufferSize: DWORD;
    dw: DWORD;

    if not OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, ref hAccessToken) then
        dw <- GetLastError;
        if dw <> ERROR_NO_TOKEN then
            RaiseLastOSError(dw);

        if not OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, ref hAccessToken) then
            RaiseLastOSError;
    try
        userToken <- GetMemory(1024);
        try
            if not GetTokenInformation(hAccessToken, TokenUser, userToken, 1024, ref dwInfoBufferSize) then
                RaiseLastOSError;
            Result <- SidToString(userToken.User.Sid);
        finally
            FreeMemory(userToken);
    finally
        CloseHandle(hAccessToken);
1
Ian Boyd

Vous n'avez pas spécifié quelle langue vous voulez. Mais si vous êtes prêt pour C #, cet article propose à la fois la méthode WMI et une méthode plus rapide (bien que plus détaillée) utilisant l'API Win32.

http://www.codeproject.com/KB/cs/processownersid.aspx

Je ne pense pas qu'il y ait actuellement une autre façon de faire cela sans utiliser WMI ou l'API Win32.

0
Mel Green

Celui-ci est le plus court de tous je crois. 

UserPrincipal.Current.Sid;

Disponible avec .net> = 3.5 

0
nullpotent

Cette question est étiquetée comme c++ Et je réponds dans la langue c++. Je recommande donc l’utilisation deWMItool:

Donc, en tant queWMIcommandes dans powershell, la commande ci-dessous obtient SID de system-pc1 utilisateur:

Get-WmiObject win32_useraccount -Filter "name = 'system-pc1'" | Select-Object sid

Tout d’abord, vous devez obtenir la version username actuelle avec ci-dessous code:

char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);

Maintenant, vous pouvez essayer avec le langage WQL et exécuter cette requête dans c++ comme ci-dessous (dans cet exemple, j'ai utilisé de system-pc1 nom d'utilisateur dans la requête WQL_WIN32_USERACCOUNT_QUERY:

#define                 NETWORK_RESOURCE                    "root\\CIMV2"
#define                 WQL_LANGUAGE                        "WQL"
#define                 WQL_WIN32_USERACCOUNT_QUERY         "SELECT * FROM Win32_Useraccount where name='system-pc1'"
#define                 WQL_SID                             "SID"

IWbemLocator            *pLoc = 0;              // Obtain initial locator to WMI to a particular Host computer
IWbemServices           *pSvc = 0;              // To use of connection that created with CoCreateInstance()
ULONG                   uReturn = 0;
HRESULT                 hResult = S_OK;         // Result when we initializing
IWbemClassObject        *pClsObject = NULL;     // A class for handle IEnumWbemClassObject objects
IEnumWbemClassObject    *pEnumerator = NULL;    // To enumerate objects
VARIANT                 vtSID = { 0 };          // OS name property

// Initialize COM library
hResult = CoInitializeEx(0, COINIT_MULTITHREADED);
if (SUCCEEDED(hResult))
{
    // Initialize security
    hResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT,
        RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    if (SUCCEEDED(hResult))
    {
        // Create only one object on the local system
        hResult = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
            IID_IWbemLocator, (LPVOID*)&pLoc);

        if (SUCCEEDED(hResult))
        {
            // Connect to specific Host system namespace
            hResult = pLoc->ConnectServer(TEXT(NETWORK_RESOURCE), NULL, NULL,
                0, NULL, 0, 0, &pSvc);
            if (SUCCEEDED(hResult))
            {
                /* Set the IWbemServices proxy
                * So the impersonation of the user will be occurred */
                hResult = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE,
                    NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE,
                    NULL, EOAC_NONE);
                if (SUCCEEDED(hResult))
                {
                    /* Use the IWbemServices pointer to make requests of WMI
                    * For example, query for user account */
                    hResult = pSvc->ExecQuery(TEXT(WQL_LANGUAGE), TEXT(WQL_WIN32_USERACCOUNT_QUERY),
                        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
                    if (SUCCEEDED(hResult))
                    {
                        // Go to get the next object from IEnumWbemClassObject
                        pEnumerator->Next(WBEM_INFINITE, 1, &pClsObject, &uReturn);
                        if (uReturn != 0)
                        {
                            // Get the value of the "sid, ..." property
                            pClsObject->Get(TEXT(WQL_SID), 0, &vtSID, 0, 0);
                            VariantClear(&vtSID);

                            // Print SID
                            wcout << vtSID.bstrVal;

                            pClsObject->Release();
                            pClsObject = NULL;
                        }
                    }
                }
            }
        }
    }

    // Cleanup
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    // Uninitialize COM library
    CoUninitialize();

Cet exemple fonctionne correctement!

0