【问题标题】:How can I get the SID of the current Windows account?如何获取当前 Windows 帐户的 SID?
【发布时间】:2010-09-20 01:22:53
【问题描述】:

我正在寻找一种简单的方法来获取当前 Windows 用户帐户的 SID。我知道我可以通过 WMI 做到这一点,但我不想走那条路。

向所有用 C# 回答的人道歉,因为他们没有指定它是 C++。 :-)

【问题讨论】:

  • 编程语言/环境?

标签: c# c++ windows winapi sid


【解决方案1】:

在 Win32 中,调用 GetTokenInformation,传递令牌句柄和 TokenUser 常量。它将为您填写TOKEN_USER 结构。其中的元素之一是用户的 SID。它是一个 BLOB(二进制),但您可以使用 ConvertSidToStringSid 将其转换为字符串。

要获取当前令牌句柄,请使用OpenThreadTokenOpenProcessToken

如果您更喜欢 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(),它返回当前用户 ID:

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

【讨论】:

    【解决方案2】:
    ATL::CAccessToken accessToken;
    ATL::CSid currentUserSid;
    if (accessToken.GetProcessToken(TOKEN_READ | TOKEN_QUERY) &&
        accessToken.GetUser(&currentUserSid))
        return currentUserSid.Sid();
    

    【讨论】:

    • 这个很简洁。
    【解决方案3】:

    这应该可以满足您的需求:

    使用 System.Security.Principal;

    ...

    var sid = WindowsIdentity.GetCurrent().User;

    WindowsIdentity 的 User 属性返回 SID,每个 MSDN Docs

    【讨论】:

      【解决方案4】:

      CodeProject 有几种不同的方法您可以尝试...您没有提到您想要解决方案的语言。

      如果您想通过批处理文件或其他方式访问它,您可以查看Sysinternals 的 PsGetSid。它将 SID 转换为名称,反之亦然。

      【讨论】:

        【解决方案5】:

        在 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;");

        【讨论】:

          【解决方案6】:

          我找到了另一种获取 SID 的方法:

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

          【讨论】:

          • 这是域的 sid 不是用户帐户的 id.User.ToString() 用于用户的 sid
          【解决方案7】:

          在本机代码中:

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

          【讨论】:

            【解决方案8】:

            这个问题被标记为c++,我用c++语言回答,所以我推荐使用WMI工具:

            所以,作为powershell 中的WMI 命令,下面的命令获取SID of system-pc1 用户:

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

            首先,您需要使用下面的code 获取当前的username

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

            现在您可以尝试使用WQL 语言并在c++ 中执行此查询,如下所示(在此示例中,我在WQL_WIN32_USERACCOUNT_QUERY 查询中使用了system-pc1 用户名:

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

            这个例子运行正常!

            【讨论】:

              【解决方案9】:

              你没有指定你想要什么语言。但是,如果您喜欢 C#,本文提供了 WMI 方法以及利用 Win32 API 的更快(但更冗长)的方法。

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

              我认为目前没有其他方法可以在不使用 WMI 或 Win32 API 的情况下执行此操作。

              【讨论】:

                【解决方案10】:

                这是我认为最短的一个。

                UserPrincipal.Current.Sid;
                

                适用于 .net >= 3.5

                【讨论】:

                  【解决方案11】:

                  在 cmd.exe 中

                  whoami /用户

                  如果您以编程方式需要它,请询问更详细的说明

                  【讨论】:

                  • 提问者特别要求提供 C++ 解决方案。
                  • 很公平,调用system("whoami /user"); 在技术上是一个 C++ 解决方案,我应该指定我想通过直接调用 Windows API 来做到这一点。
                  猜你喜欢
                  • 2017-05-12
                  • 1970-01-01
                  • 2019-10-16
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-04-17
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-11-12
                  相关资源
                  最近更新 更多