كيفية الحصول على تسجيل الدخول SID في C#
-
23-09-2019 - |
سؤال
كيف يمكن للمرء أن يسترجع Windows Logon SID في C# .NET؟ (ليس المستخدم SID ، ولكن الفريدة الجديدة لكل جلسة)
المحلول
أخشى أن تضطر إلى اللجوء إلى استخدام P/Invoke. هناك مثال على كيفية القيام بذلك في pinvoke.net (يرجى الاطلاع على أسفل الصفحة):
Result = GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenSessionId , TokenInformation , TokenInfLength , out TokenInfLength );
يرجى ملاحظة أنني غيرت المثال عن طريق تغيير سطر واحد فقط ، استبدلت TOKEN_INFORMATION_CLASS.TokenUser
مع TOKEN_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;
}
}
}
NB لقد اختبرته على جهاز X64 الخاص بي ، لذا يرجى إيلاء اهتمام وثيق TokenInformation.ToInt64()
قطعة من الكود ، ربما يجب أن تستبدلها TokenInformation.ToInt32()
نصائح أخرى
System.Security.principal.windowsidentity.getCurrent (). user.accountdomainsid - قد تفعل الخدعة؟
انا اعرف ان هذا ملصق قديم. لقد واجهت هذه المشكلة حيث اضطررت إلى الحصول على معرف جلسة ICA ومعرف جلسة RDP لجعل برنامج يقوم بجمع المتغيرات الصحيحة لكل نوع من أنواع الاتصال عن بُعد. يقع معرف الجلسة الحالي في 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();
}
}
}