7
votes

Comment obtenir un identifiant unique pour la session de connexion actuelle de l'utilisateur dans Windows - C #

Je dois obtenir une valeur qui identifie de manière unique la session de connexion de l'utilisateur de Windows actuelle. Ceci est pour une application WinForms, pas ASP.NET. Je vais récupérer cela de plusieurs processus afin qu'il doit renvoyer la même valeur lorsqu'elle est extraite dans la même session de connexion. Il doit seulement être unique sur la machine actuelle pendant la durée de toutes les sessions utilisateur - par ex. jusqu'à ce que la machine soit ensuite redémarrée.

Je pense que le ID de connexion Windows Logon est le droit chose, mais semble un peu une douleur à récupérer. Y a-t-il autre chose ou un moyen plus simple d'obtenir cela?

Je vais utiliser l'ID pour inclure dans une adresse d'un service de tuyaux nommé pour communiquer entre deux processus exécutés sur la machine. Je souhaite inclure l'ID de connexion pour éviter les conflits lorsqu'il y a plusieurs utilisateurs connectés, y compris peut-être plusieurs sessions du même utilisateur.


2 commentaires

Si l'utilisateur se déconnecte et se connecte, est-il acceptable d'obtenir le même ID?


Non, cela devrait être un autre identifiant car c'est une autre session.


4 Réponses :


-1
votes

Si je vous comprends correctement, vous pouvez générer un GUID


1 commentaires

Désolé, je n'ai pas précisé que cela doit être identique à partir de plusieurs processus. c'est-à-dire qu'il faut identifier la session de connexion, pas seulement être unique



0
votes

Vous pouvez essayer environnement.userdomainName & environnement.Ausername < / code>

Pour assurer un identifiant unique unique pour chaque session d'utilisateur Je suppose que vous devrez utiliser la méthode douloureuse que vous avez mentionnée - Comment obtenir le SID de connexion en C # .


7 commentaires

Et si l'utilisateur est connecté deux fois?


Le même utilisateur peut-il se connecter à une machine à deux reprises en utilisant les mêmes informations d'identification? J'ai toujours pensé que vous seriez redirigé à votre session existante. Besoin de tester je suppose. :)


@Zach oui je suppose que vous pouvez. Bien que l'utilisation de RDP vous frappe à votre compte d'origine. Mais que diriez-vous d'un service en cours d'exécution avec un identifiant d'utilisateur et que l'utilisateur est connecté à la machine.


@YeTanotherUser, je suppose que je ne dirigerais pas les services comme une personne réelle, mais sous un compte de service (domaine ou local). :) Vous vous demandez si vous pouvez obtenir cela de Winstation? Vraisemblablement, même s'ils se sont connectés deux fois, ils auraient différents identifiants de winstation? Les services fonctionnent généralement dans 0, mais je le confirmerais.


@Zach, ce que vous faites est une meilleure pratique recommandée, ce dont je parlais était une solution possible. :) Si c'est une application de bureau Windows régulière (exclure le serveur Win Server, le serveur Terminal Server et Windows), je ne pense pas que c'est réalisable d'avoir deux sessions utilisateur sur la même machine. Mais alors je pourrais avoir tort.


@Yeta: un utilisateur unique peut avoir plusieurs sessions interactives avec RDP ou Server multipoint ( Microsoft.com /windows/multipoint/default.aspx ) tant que la stratégie est configurée de cette façon. Cependant, vous venez de poster un lien vers la même solution que l'OP mentionnait qu'il essayait d'éviter, de sorte que cela n'aide pas.


@Gabe: Je sais - je n'ai pas réalisé que c'était le même lien qu'après que je l'ai posté. C'est la raison pour laquelle j'ai mentionné explicitement sa même méthode douloureuse. J'ai regardé autour de vous ne pouvions pas trouver une approche alternative. BTW MPS est intéressant.



17
votes

Le moyen le plus simple d'obtenir une carte d'identité est de regarder processus.sessidid Propriété:

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


4 commentaires

Merci pour ce code utile. Veuillez noter que l'identifiant de session d'origine n'est pas unique. Lorsque l'utilisateur se déconnecte et se connecte à nouveau, cela reste la même valeur.


Yup session ID n'est pas unique, je ne sais pas pourquoi c'est la réponse acceptée


@Paulm, la session est unique au moment du moment de toutes les sessions ouvertes, et qui résout la tâche de OP: Adressant les tuyaux nommés. Lorsque l'utilisateur se déconnecte, ce sont des processus sont destructions. Ils n'interfèrent donc pas avec les sessions ultérieures de l'utilisateur. Toutefois, si le même utilisateur est connecté à différentes sessions en même temps, les résultats sont uniques.


Réponse simple! (Processus.getCurrentCrocess (). SéanceID)



5
votes

Si je comprends bien, ce dont vous avez besoin, c'est ceci:

SID: S-1-5-5-X-Y Nom: Session de connexion Description: une session de connexion. Les valeurs X et Y pour ces PEID sont différentes pour chaque session.

identificateurs de sécurité bien connus dans les systèmes d'exploitation Windows http://support.microsoft.com/kb/243330

Quelqu'un a demandé quelque chose de similaire ici:

Comment obtenir la connexion SID en C #

Ils ont une bonne réponse là-bas, mais je veux ajouter mon propre

C'est ma solution: < Pré> xxx


0 commentaires