Как получить уникальный идентификатор для сеанса входа текущего пользователя в windows - c # - PullRequest
2 голосов
/ 19 мая 2011

Мне нужно получить значение, которое однозначно определяет сеанс входа текущего пользователя Windows.Это для приложения winforms, а не ASP.NET.Я получу это из нескольких процессов, поэтому оно должно возвращать одно и то же значение при получении в течение одного сеанса входа.Он должен быть уникальным только на текущем компьютере в течение всех пользовательских сеансов, например, до следующего перезапуска компьютера.

Я думаю, Идентификатор входа в Windows - это правильная вещь, но, похоже, ее сложно найти.Есть ли что-нибудь еще или более простой способ получить это?

Я буду использовать идентификатор для включения в адрес службы именованных каналов для связи между двумя процессами, запущенными на машине.Я хочу включить идентификатор входа в систему, чтобы избежать конфликтов, когда вошли несколько пользователей, в том числе, возможно, несколько сеансов одного и того же пользователя.

Ответы [ 4 ]

11 голосов
/ 05 июня 2013

Самый простой способ получить идентификатор сессии - посмотреть на Process.SessionId свойство:

System.Diagnostics.Process.GetCurrentProcess().SessionId

Значение совпадает с GetTokenInformation (..., TokenSessionId, ...) .

Примечание: Следует иметь в виду, что идентификатор сеанса не является идентификатором входа в систему . Например, в процессе повышения прав Win7, запущенном под одним и тем же пользователем в одном и том же сеансе, будет другой LogonId (сопоставимый с не повышенным), но будет иметь тот же SessionId. Даже запуск процесса без повышенных прав с RunAs, явно указывающими учетные данные одного и того же пользователя, создаст новый идентификатор входа в систему. Такое поведение имеет значение, например, когда вы подключаете сетевые диски. Начиная с Vista, процесс с одним токеном LogonId не будет видеть сетевые каталоги, сопоставленные с другим LogonId, даже если процессы выполняются в том же сеансе и под тем же пользователем.

Ниже приведен пример приложения, которое вы можете запустить на разных сессиях / кредитах, чтобы увидеть разницу:

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();
            }
        }
    }
}
3 голосов
/ 02 марта 2015

Как я понимаю, вам нужно это:

SID: S-1-5-5-X-Y Имя: сеанс входа Описание: сеанс входа. Значения X и Y для этих SID различны для каждого сеанса.

Известные идентификаторы безопасности в операционных системах Windows http://support.microsoft.com/kb/243330

Кто-то спросил здесь что-то похожее:

Как получить SID для входа в C #

У них там хороший ответ, но я хочу добавить свой

Это мое решение:

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 голосов
/ 19 мая 2011

Вы можете попробовать Environment.UserDomainName & Environment.UserName

Чтобы обеспечить уникальный идентификатор для каждой пользовательской сессии Я думаю, вам придется использовать болезненный метод, который вы упомянули - Как получить SID для входа в C # .

0 голосов
/ 19 мая 2011

Если я вас правильно понимаю, вы можете сгенерировать GUID

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...