How to get a Unique ID for the current user's logon session in windows - c#

后端 未结 4 1451
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-10 18:05

I need to get a value that uniquely identifies the current windows user\'s logon session. This is for a winforms app, not ASP.NET. I\'ll be retrieving this from within multi

相关标签:
4条回答
  • 2020-12-10 18:34

    If I understand you correctly you can generate a GUID

    0 讨论(0)
  • 2020-12-10 18:36

    The easiest way to get Session Id is to look at Process.SessionId property:

    System.Diagnostics.Process.GetCurrentProcess().SessionId
    

    The value is the same as returned by GetTokenInformation(...,TokenSessionId,...).

    Note: One thing you should keep in mind is that Session Id is not a Logon Id. For example, on Win7 elevated process launched under the same user in the same session will have different LogonId (copmaring to non-elevated one), but will have the same SessionId. Even runniung non-elevated process with RunAs explicitly specifying credentials of the same user will create new Logon Sesison Id. Such behavior has meaning, for example, when you map network drives. Since Vista, a process with one token LogonId will not see network dirves mapped with another LogonId, even if processes are running in the same session and under same user.

    Below is the sample app that you can launch on different sessions/creds to see the difference:

    using System;
    using System.Runtime.InteropServices;
    
    namespace GetCurrentSessionId
    {
        class Program
        {
    
            enum TokenInformationClass
            {
                TokenUser = 1,
                TokenGroups,
                TokenPrivileges,
                TokenOwner,
                TokenPrimaryGroup,
                TokenDefaultDacl,
                TokenSource,
                TokenType,
                TokenImpersonationLevel,
                TokenStatistics,
                TokenRestrictedSids,
                TokenSessionId,
                TokenGroupsAndPrivileges,
                TokenSessionReference,
                TokenSandBoxInert,
                TokenAuditPolicy,
                TokenOrigin
            }
    
            enum TokenType
            {
                TokenPrimary = 1, 
                TokenImpersonation
            }
    
            enum SecurityImpersonationLevel 
            { 
                SecurityAnonymous,
                SecurityIdentification,
                SecurityImpersonation,
                SecurityDelegation
            }
    
            [StructLayout(LayoutKind.Sequential)]
            struct TokenStatistics
            {
                public Int64 TokenId;
                public Int64 AuthenticationId;
                public Int64 ExpirationTime;
                public TokenType TokenType;
                public SecurityImpersonationLevel ImpersonationLevel;
                public Int32 DynamicCharged;
                public Int32 DynamicAvailable;
                public Int32 GroupCount;
                public Int32 PrivilegeCount;
                public Int64 ModifiedId;
            }
    
            struct TokenOrigin
            {
                public Int64 OriginatingLogonSession;
            }
    
            [DllImport("advapi32.dll", EntryPoint = "GetTokenInformation", SetLastError = true)]
            static extern bool GetTokenInformation(
                IntPtr tokenHandle,
                TokenInformationClass tokenInformationClass,
                IntPtr tokenInformation,
                int tokenInformationLength,
                out int ReturnLength);
    
            public const int ERROR_INSUFFICIENT_BUFFER = 0x7a;
    
            static void Main(string[] args)
            {
                try
                {
                    Console.WriteLine("Session Id: {0}", System.Diagnostics.Process.GetCurrentProcess().SessionId);
    
                    IntPtr tokenInfo;
                    bool result;
                    int infoSize;
    
                    IntPtr hToken = System.Security.Principal.WindowsIdentity.GetCurrent().Token;
    
                    result = GetTokenInformation(hToken, TokenInformationClass.TokenStatistics, IntPtr.Zero, 0, out infoSize);
                    if (!result && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
                    {
                        tokenInfo = Marshal.AllocHGlobal(infoSize);
                        result = GetTokenInformation(hToken, TokenInformationClass.TokenStatistics, tokenInfo, infoSize, out infoSize);
                        if (result)
                        {
                            TokenStatistics tokenStats = (TokenStatistics)Marshal.PtrToStructure(tokenInfo, typeof(TokenStatistics));
                            Console.WriteLine("LogonId: 0x{0:X16}", tokenStats.AuthenticationId);
                        }
                        else
                        {
                            Console.Error.WriteLine("LogonId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error());
                        }
                        Marshal.FreeHGlobal(tokenInfo);
                    }
                    else
                    {
                        Console.Error.WriteLine("LogonId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error());
                    }
    
    
                    tokenInfo = Marshal.AllocHGlobal(sizeof (Int32));
                    result = GetTokenInformation(hToken, TokenInformationClass.TokenSessionId, tokenInfo, sizeof (Int32), out infoSize);
                    if (result)
                    {
                        int tokenSessionId = Marshal.ReadInt32(tokenInfo);
                        Console.WriteLine("TokenSessionId: {0}", tokenSessionId);
                    }
                    else
                    {
                        Console.Error.WriteLine("TokenSessionId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error());
                    }
    
                    Marshal.FreeHGlobal(tokenInfo);
    
    
                    result = GetTokenInformation(hToken, TokenInformationClass.TokenOrigin, IntPtr.Zero, 0, out infoSize);
                    if (!result && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
                    {
                        tokenInfo = Marshal.AllocHGlobal(infoSize);
                        result = GetTokenInformation(hToken, TokenInformationClass.TokenOrigin, tokenInfo, infoSize, out infoSize);
                        if (result)
                        {
                            TokenOrigin tokenOrigin = (TokenOrigin) Marshal.PtrToStructure(tokenInfo, typeof (TokenOrigin));
                            Console.WriteLine("OriginatingSessionId: 0x{0:X16}", tokenOrigin.OriginatingLogonSession);
                        }
                        else
                        {
                            Console.WriteLine("OriginatingSessionId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error());
                        }
                        Marshal.FreeHGlobal(tokenInfo);
                    }
                    else
                    {
                        Console.WriteLine("OriginatingSessionId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error());
                    }
    
                    Console.WriteLine("Press any key...");
                    Console.ReadKey();
    
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine("Unexpected error: {0}", ex);
                    Console.ReadKey();
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-10 18:46

    As I understand, what you need is this:

    SID: S-1-5-5-X-Y Name: Logon Session Description: A logon session. The X and Y values for these SIDs are different for each session.

    Well-known security identifiers in Windows operating systems http://support.microsoft.com/kb/243330

    Somebody asked for something similar here:

    How to get the logon SID in C#

    They have a good answer there, but I want to add my own

    This is my solution:

    using System;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    
    namespace TestLogonSid
    {
        public partial class Form1 : Form
        {
    
            private delegate bool EnumDesktopProc(string lpszDesktop, IntPtr lParam);
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click_1(object sender, EventArgs e)
            {
    
                this.textBox1.Text = GetLogonSid.getLogonSid();
            }
    
    
        }
    
        public class GetLogonSid
        {
            //The SID structure that identifies the user that is currently associated with the specified object. 
            //If no user is associated with the object, the value returned in the buffer pointed to by lpnLengthNeeded is zero. 
            //Note that SID is a variable length structure. 
            //You will usually make a call to GetUserObjectInformation to determine the length of the SID before retrieving its value.
            private const int UOI_USER_SID = 4;
    
            //GetUserObjectInformation function
            //Retrieves information about the specified window station or desktop object.
            [DllImport("user32.dll")]
            static extern bool GetUserObjectInformation(IntPtr hObj, int nIndex, [MarshalAs(UnmanagedType.LPArray)] byte[] pvInfo, int nLength, out uint lpnLengthNeeded);
    
    
            //GetThreadDesktop function
            //Retrieves a handle to the desktop assigned to the specified thread.
            [DllImport("user32.dll")]
            private static extern IntPtr GetThreadDesktop(int dwThreadId);
    
    
            //GetCurrentThreadId function
            //Retrieves the thread identifier of the calling thread.
            [DllImport("kernel32.dll")]
            public static extern int GetCurrentThreadId();
    
            //ConvertSidToStringSid function
            //The ConvertSidToStringSid function converts a security identifier (SID) to a string format suitable for display, storage, or transmission.
            //To convert the string-format SID back to a valid, functional SID, call the ConvertStringSidToSid function.
    
            [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
            static extern bool ConvertSidToStringSid(
                [MarshalAs(UnmanagedType.LPArray)] byte[] pSID,
                out IntPtr ptrSid);
    
    
            /// <summary>
            /// The getLogonSid function returns the Logon Session string
            /// </summary>
            /// <returns></returns>
            public static string getLogonSid()
            {
                string sidString = "";
                IntPtr hdesk = GetThreadDesktop(GetCurrentThreadId());
                byte[] buf = new byte[100];
                uint lengthNeeded;
                GetUserObjectInformation(hdesk, UOI_USER_SID, buf, 100, out lengthNeeded);
                IntPtr ptrSid;
                if (!ConvertSidToStringSid(buf, out ptrSid))
                    throw new System.ComponentModel.Win32Exception();
                try
                {
                    sidString = Marshal.PtrToStringAuto(ptrSid);
                }
                catch
                {
                }
                return sidString;
            }
    
        }
    }
    
    0 讨论(0)
  • 2020-12-10 18:55

    You can try Environment.UserDomainName & Environment.UserName

    To ensure a unique id for each user session I guess you'll have to use the painful method you mentioned - How to get the logon SID in C#.

    0 讨论(0)
提交回复
热议问题