Как я могу получить SID текущей учетной записи Windows? - PullRequest
29 голосов
/ 30 октября 2008

Я ищу простой способ получить SID для текущей учетной записи пользователя Windows. Я знаю, что могу сделать это через WMI, но я не хочу идти по этому пути.

Приношу извинения всем, кто ответил на C # за то, что он не указал C ++. : -)

Ответы [ 10 ]

49 голосов
/ 30 октября 2008

В Win32 вызовите GetTokenInformation , передав дескриптор токена и константу TokenUser. Он заменит для вас структуру TOKEN_USER . Одним из элементов там является SID пользователя. Это BLOB (двоичный файл), но вы можете превратить его в строку, используя ConvertSidToStringSid .

Чтобы получить текущий дескриптор токена, используйте OpenThreadToken или OpenProcessToken .

Если вы предпочитаете ATL, у него есть класс CAccessToken , в котором есть много всего интересного.

.NET имеет свойство Thread.CurrentPrinciple , которое возвращает ссылку на IPrincipal. Вы можете получить SID:

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

Также в .NET вы можете использовать WindowsIdentity.GetCurrent (), который возвращает текущий идентификатор пользователя:

WindowsIdentity identity = WindowsIdentity.GetCurrent();
if (identity != null)
    Console.WriteLine(identity.User);
7 голосов
/ 13 ноября 2012
ATL::CAccessToken accessToken;
ATL::CSid currentUserSid;
if (accessToken.GetProcessToken(TOKEN_READ | TOKEN_QUERY) &&
    accessToken.GetUser(&currentUserSid))
    return currentUserSid.Sid();
7 голосов
/ 30 октября 2008

Это должно дать вам то, что вам нужно:

с использованием System.Security.Principal;

...

var sid = WindowsIdentity.GetCurrent (). User;

Свойство User WindowsIdentity возвращает SID для Документов MSDN

2 голосов
/ 13 января 2012

Я нашел другой способ получить SID:

System.Security.Principal.WindowsIdentity id = System.Security.Principal.WindowsIdentity.GetCurrent();
string sid = id.User.AccountDomainSid.ToString();
2 голосов
/ 30 октября 2008

В C # вы можете использовать либо

using Microsoft.Win32.Security;

...

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

Sid sidUser = new Sid (username);

Или ...

using System.Security.AccessControl;

using System.Security.Principal;

...

WindowsIdentity m_Self = WindowsIdentity.GetCurrent();

SecurityIdentifier m_SID = m_Self.Owner;");

2 голосов
/ 30 октября 2008

CodeProject имеет несколько различных методов, которые вы можете попробовать ... Вы не упомянули, на каких языках вы хотели найти решение.

Если вы хотите получить к нему доступ через пакетный файл или что-то еще, вы можете выглядеть как PsGetSid по Sysinternals . Преобразует SID в имена и наоборот.

1 голос
/ 16 августа 2017

А в нативном коде:

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);
0 голосов
/ 12 ноября 2018

Этот вопрос помечен как c++ И я отвечаю на c++ языке, поэтому я рекомендую использовать WMI tool:

Итак, As WMI команды в powershell, ниже команда get SID из system-pc1 пользователь:

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

Во-первых, вам нужно получить ток username с сильфоном code:

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

Теперь вы можете попробовать язык WQL и выполнить этот запрос на c++, как показано ниже (в этом примере я использовал system-pc1 имя пользователя в 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();

Этот пример работает правильно!

0 голосов
/ 23 октября 2012

Это самый короткий из них, я верю.

UserPrincipal.Current.Sid;

Доступно с .net> = 3,5

0 голосов
/ 30 октября 2008

Вы не указали, какой язык вы хотите. Но если вы хотите использовать C #, эта статья предлагает как метод WMI, так и более быстрый (хотя и более подробный) метод с использованием Win32 API.

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

Я не думаю, что в настоящее время есть другой способ сделать это без использования WMI или Win32 API.

...