c# - C#获取登录SID的方法

标签 c# .net authentication sid

如何在 C# .net 中检索 Windows 登录 SID? (不是用户 SID,而是每个 session 唯一的新 SID)

最佳答案

恐怕您不得不诉诸于使用 P/Invoke。在 pinvoke.net 有一个如何做的例子。 (请看页面底部):

Result = GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenSessionId , TokenInformation , TokenInfLength , out TokenInfLength );

请注意,我通过更改一行来更改示例,我替换了 TOKEN_INFORMATION_CLASS.TokenUserTOKEN_INFORMATION_CLASS.TokenSessionId这正是您所需要的。

希望这对您有所帮助。

更新:这是工作代码(至少在我的机器上):

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace LinqTest
{
    public class ClsLookupAccountName
    {
        public const uint SE_GROUP_LOGON_ID = 0xC0000000; // from winnt.h
        public const int TokenGroups = 2; // from TOKEN_INFORMATION_CLASS

        enum TOKEN_INFORMATION_CLASS
        {
            TokenUser = 1,
            TokenGroups,
            TokenPrivileges,
            TokenOwner,
            TokenPrimaryGroup,
            TokenDefaultDacl,
            TokenSource,
            TokenType,
            TokenImpersonationLevel,
            TokenStatistics,
            TokenRestrictedSids,
            TokenSessionId,
            TokenGroupsAndPrivileges,
            TokenSessionReference,
            TokenSandBoxInert,
            TokenAuditPolicy,
            TokenOrigin
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SID_AND_ATTRIBUTES
        {
            public IntPtr Sid;
            public uint Attributes;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct TOKEN_GROUPS
        {
            public int GroupCount;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
            public SID_AND_ATTRIBUTES[] Groups;
        };

        // Using IntPtr for pSID instead of Byte[]
        [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
        static extern bool ConvertSidToStringSid(IntPtr pSID, out IntPtr ptrSid);

        [DllImport("kernel32.dll")]
        static extern IntPtr LocalFree(IntPtr hMem);

        [DllImport("advapi32.dll", SetLastError = true)]
        static extern bool GetTokenInformation(
            IntPtr TokenHandle,
            TOKEN_INFORMATION_CLASS TokenInformationClass,
            IntPtr TokenInformation,
            int TokenInformationLength,
            out int ReturnLength);

        public static string GetLogonId()
        {
            int TokenInfLength = 0;
            // first call gets lenght of TokenInformation
            bool Result = GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenGroups, IntPtr.Zero, TokenInfLength, out TokenInfLength);
            IntPtr TokenInformation = Marshal.AllocHGlobal(TokenInfLength);
            Result = GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenGroups, TokenInformation, TokenInfLength, out TokenInfLength);

            if (!Result)
            {
                Marshal.FreeHGlobal(TokenInformation);
                return string.Empty;
            }

            string retVal = string.Empty;
            TOKEN_GROUPS groups = (TOKEN_GROUPS)Marshal.PtrToStructure(TokenInformation, typeof(TOKEN_GROUPS));
            int sidAndAttrSize = Marshal.SizeOf(new SID_AND_ATTRIBUTES());
            for (int i = 0; i < groups.GroupCount; i++)
            {
                SID_AND_ATTRIBUTES sidAndAttributes = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(
                    new IntPtr(TokenInformation.ToInt64() + i * sidAndAttrSize + IntPtr.Size), typeof(SID_AND_ATTRIBUTES));
                if ((sidAndAttributes.Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID)
                {
                    IntPtr pstr = IntPtr.Zero;
                    ConvertSidToStringSid(sidAndAttributes.Sid, out pstr);
                    retVal = Marshal.PtrToStringAuto(pstr);
                    LocalFree(pstr);
                    break;
                }
            }

            Marshal.FreeHGlobal(TokenInformation);
            return retVal;
        }
    }
}

注意我在我的 x64 机器上测试过它,所以请密切关注 TokenInformation.ToInt64()一段代码,也许您应该将其替换为 TokenInformation.ToInt32()

关于c# - C#获取登录SID的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2146153/

相关文章:

c# - 将多行插入 MS SQL Server 并检索所有新表 ID 的背面

c# - 如何对方法的属性存在进行 NUnit 测试

c# - 将 List<Double> 绑定(bind)到 WinForms-Listbox

c# - 如何将控件绑定(bind)到DataGrid中的当前行?

rest - 如何使用Azure AD对第三方应用程序的用户进行身份验证?

c# - 覆盖 webBrowser 点击事件

c# - foo.Include(x => x.bar.Select(y => y.baz) 在 C# 中包含 foo.bar 吗?

c# - 如何在 WPF 中自定义组合框按钮的外观

swift - 从 SharedWebCredential 获取所有登录信息

authentication - 如何使用 Windows 7 查看我的 PC 的登录历史记录