2010-01-27 4 views
8

C# .net에서 Windows 로그온 SID를 검색하는 방법은 무엇입니까? (사용자 SID는 아니지만 각 세션에 대해 고유 한 새 ID)C#에서 로그온 SID를 얻는 방법

+0

Windwos 환경에서 SID는 세션 ID가 아닌 보안 식별자를 나타냅니다. 세션 ID를 얻으려면'System.Diagnostics.Process.GetCurrentProcess(). SessionId'를 사용하십시오. 자세한 내용은 [my answer here] (http://stackoverflow.com/a/16942663/725903) – mistika

답변

6

P/Invoke를 사용해야 할까봐 걱정됩니다. pinvoke.net에 그것을 수행하는 방법의 예 (페이지 하단 참조)있다 :

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

난 그냥 한 줄을 변경하여 예를 변경 있음을 유의하시기 바랍니다, 나는 당신이 필요로 정확히 어떤 TOKEN_INFORMATION_CLASS.TokenSessionIdTOKEN_INFORMATION_CLASS.TokenUser 교체 .

희망이 도움이됩니다.

업데이트 :

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

N.B. : 여기에 코드 (적어도 내 컴퓨터에) 작업이야 x64 컴퓨터에서 테스트 했으므로 코드 TokenInformation.ToInt32()

+0

불행히도 작동하지 않습니다. 그것은 아무것도 반환하지 않습니다. 이 (http://msdn.microsoft.com/en-us/library/aa379626%28VS.85%29.aspx)에 따르면 터미널 서버에서만 작동하므로 필요한 세션 ID가 아닐 수도 있습니다. – Jos

+0

다른 버전의 코드를 추가했는데 내 컴퓨터에서 작동합니다. 어떤 것이 명확하지 않은지 내게 언제든지 물어보십시오. –

+0

감사합니다. 이 하나가 완벽하게 작동합니다. TokenGroups 대신 TokenLogonSid를 사용했지만 Windows Vista 및 7에서만 작동합니다. – Jos

1

System.Security.Principal.WindowsIdentity.GetCurrent(). User.AccountDomainSid - 트릭을 수행 할 수 있습니까?

+1

을 참조하십시오. 로그온 세션 ID SilverSkin에 대해 물어 –

+1

나는 사용자 SID가 세션간에 변경되지 않은 것 같아요,하지만 각 로그인 토큰이 만들어집니다, 그것을 통해 액세스 할 수 있어야합니다 ... GetCurrent(). User.Token? – SilverSkin

+0

토큰은 실제로 필요한 것이지만 사용 가능한 SID로 변환해야합니다. – Jos

1

으로 교체해야합니다. TokenInformation.ToInt64() 코드에주의를 기울여주십시오. 이전 게시물 인 것으로 알고 있습니다. ICA 세션 ID와 RDP 세션 ID를 얻어야 만 프로그램이 각 유형의 원격 연결에 대해 올바른 변수를 수집해야하므로이 문제가 발생했습니다. 현재 세션 ID는 Regedit HKEY_CURRENT_USER \ Remote *에 있습니다. WTS에 대한 대안을 찾을 수 없어서 여기에 내 솔루션을 게시하고 있습니다.

// Prints out ICA or RDP session ID of current user 

using System; 
using Microsoft.Win32; 

namespace ViaRegedit 
{ 
    class Program03 
    { 
     static void Main(string[] args) 
     { 
      // Obtain an instance of RegistryKey for the CurrentUser registry 
      RegistryKey rkCurrentUser = Registry.CurrentUser; 
      // Obtain the test key (read-only) and display it. 
      RegistryKey rkTest = rkCurrentUser.OpenSubKey("Remote"); 
      foreach (string valueName in rkTest.GetSubKeyNames()) 
      { 
       //Getting path to RDP/Citrix session ID 
       string RDPICApath = ""; 
       if (rkTest.OpenSubKey(valueName) != null && rkTest.OpenSubKey(valueName) != null) { RDPICApath = rkTest.OpenSubKey(valueName).ToString(); } 
       Console.WriteLine("Getting CurrentUser ICA-RDP path from string = " + RDPICApath); 

       //Seperating RDPICApath to get session number 
       string RDPICAnumber = RDPICApath.Substring(RDPICApath.LastIndexOf('\\') + 1); 
       Console.WriteLine("Current User RDPICAnumber = " + RDPICAnumber); 
      } 
      rkTest.Close(); 
      rkCurrentUser.Close(); 
      Console.ReadLine(); 
     } 
    } 

} 
관련 문제