2015-05-08 19 views
6

Tôi đang gặp khó khăn trong việc sử dụng một trường hợp sử dụng rất cụ thể. Ứng dụng được đề cập có hai thành phần: dịch vụ Windows cần chạy trong ngữ cảnh đặc quyền bên ngoài màn hình (nghĩa là chấp nhận kết nối khi người dùng đăng nhập hoặc không) và ứng dụng Winforms của ứng dụng khách. Dịch vụ này chấp nhận các kết nối websocket và yêu cầu kết nối thành công, nó được yêu cầu đăng nhập người dùng một cách tương tác (vào máy tính để bàn) và sinh ra một quá trình như người dùng đó với truy cập máy tính để bàn. Tôi đã sử dụng các liên kết sau và trong khi họ có thể mạo danh người dùng, họ không thực sự đăng nhập người dùng vào máy tính để bàn, tức là nếu tôi xem hệ thống bằng VNC hoặc nếu tôi thử nghiệm hệ thống cục bộ của mình, người dùng không đăng nhập. Tuy nhiên, quá trình này được tạo ra như người dùng, nhưng rõ ràng là không có quyền truy cập máy tính để bàn.Dịch vụ quản trị: đăng nhập người dùng vào máy tính để bàn, sinh ra một quy trình có thể tương tác với máy tính để bàn

Có ai có mẫu mã sẽ đăng nhập người dùng vào máy tính để bàn không?

Các liên kết và mã tôi đã cố gắng:

Using Process.Start() to start a process as a different user from within a Windows Service

How to use LogonUser properly to impersonate domain user from workgroup client công

Launch a process under another user's credentials

https://social.msdn.microsoft.com/Forums/vstudio/en-US/9fb068b0-507b-4b6b-879a-b0fbe492ba92/c-start-program-with-different-user-credentials

Mã hiện nay là:

using Cassia; 
using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Diagnostics; 
using System.DirectoryServices; 
using System.Runtime.InteropServices; 
using System.Security; 
using System.Security.Permissions; 
using System.Security.Principal; 
using System.ServiceProcess; 

namespace program 
{ 
    public partial class service 
    { 
     #region Interop 

     [StructLayout(LayoutKind.Sequential)] 
     public struct LUID 
     { 
      public UInt32 LowPart; 
      public Int32 HighPart; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct LUID_AND_ATTRIBUTES 
     { 
      public LUID Luid; 
      public UInt32 Attributes; 
     } 

     public struct TOKEN_PRIVILEGES 
     { 
      public UInt32 PrivilegeCount; 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] 
      public LUID_AND_ATTRIBUTES[] Privileges; 
     } 

     enum TOKEN_INFORMATION_CLASS 
     { 
      TokenUser = 1, 
      TokenGroups, 
      TokenPrivileges, 
      TokenOwner, 
      TokenPrimaryGroup, 
      TokenDefaultDacl, 
      TokenSource, 
      TokenType, 
      TokenImpersonationLevel, 
      TokenStatistics, 
      TokenRestrictedSids, 
      TokenSessionId, 
      TokenGroupsAndPrivileges, 
      TokenSessionReference, 
      TokenSandBoxInert, 
      TokenAuditPolicy, 
      TokenOrigin, 
      TokenElevationType, 
      TokenLinkedToken, 
      TokenElevation, 
      TokenHasRestrictions, 
      TokenAccessInformation, 
      TokenVirtualizationAllowed, 
      TokenVirtualizationEnabled, 
      TokenIntegrityLevel, 
      TokenUIAccess, 
      TokenMandatoryPolicy, 
      TokenLogonSid, 
      MaxTokenInfoClass 
     } 

     [Flags] 
     enum CreationFlags : uint 
     { 
      CREATE_BREAKAWAY_FROM_JOB = 0x01000000, 
      CREATE_DEFAULT_ERROR_MODE = 0x04000000, 
      CREATE_NEW_CONSOLE = 0x00000010, 
      CREATE_NEW_PROCESS_GROUP = 0x00000200, 
      CREATE_NO_WINDOW = 0x08000000, 
      CREATE_PROTECTED_PROCESS = 0x00040000, 
      CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000, 
      CREATE_SEPARATE_WOW_VDM = 0x00001000, 
      CREATE_SUSPENDED = 0x00000004, 
      CREATE_UNICODE_ENVIRONMENT = 0x00000400, 
      DEBUG_ONLY_THIS_PROCESS = 0x00000002, 
      DEBUG_PROCESS = 0x00000001, 
      DETACHED_PROCESS = 0x00000008, 
      EXTENDED_STARTUPINFO_PRESENT = 0x00080000 
     } 

     public enum TOKEN_TYPE 
     { 
      TokenPrimary = 1, 
      TokenImpersonation 
     } 

     public enum SECURITY_IMPERSONATION_LEVEL 
     { 
      SecurityAnonymous, 
      SecurityIdentification, 
      SecurityImpersonation, 
      SecurityDelegation 
     } 

     [Flags] 
     enum LogonFlags 
     { 
      LOGON_NETCREDENTIALS_ONLY = 2, 
      LOGON_WITH_PROFILE = 1 
     } 

     enum LOGON_TYPE 
     { 
      LOGON32_LOGON_INTERACTIVE = 2, 
      LOGON32_LOGON_NETWORK, 
      LOGON32_LOGON_BATCH, 
      LOGON32_LOGON_SERVICE, 
      LOGON32_LOGON_UNLOCK = 7, 
      LOGON32_LOGON_NETWORK_CLEARTEXT, 
      LOGON32_LOGON_NEW_CREDENTIALS 
     } 

     enum LOGON_PROVIDER 
     { 
      LOGON32_PROVIDER_DEFAULT, 
      LOGON32_PROVIDER_WINNT35, 
      LOGON32_PROVIDER_WINNT40, 
      LOGON32_PROVIDER_WINNT50 
     } 

     struct SECURITY_ATTRIBUTES 
     { 
      public uint Length; 
      public IntPtr SecurityDescriptor; 
      public bool InheritHandle; 
     } 

     [Flags] 
     enum SECURITY_INFORMATION : uint 
     { 
      OWNER_SECURITY_INFORMATION = 0x00000001, 
      GROUP_SECURITY_INFORMATION = 0x00000002, 
      DACL_SECURITY_INFORMATION = 0x00000004, 
      SACL_SECURITY_INFORMATION = 0x00000008, 
      UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000, 
      UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000, 
      PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000, 
      PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000 
     } 

     [StructLayoutAttribute(LayoutKind.Sequential)] 
     struct SECURITY_DESCRIPTOR 
     { 
      public byte revision; 
      public byte size; 
      public short control; // public SECURITY_DESCRIPTOR_CONTROL control; 
      public IntPtr owner; 
      public IntPtr group; 
      public IntPtr sacl; 
      public IntPtr dacl; 
     } 

     struct STARTUPINFO 
     { 
      public uint cb; 
      [MarshalAs(UnmanagedType.LPTStr)] 
      public string Reserved; 
      [MarshalAs(UnmanagedType.LPTStr)] 
      public string Desktop; 
      [MarshalAs(UnmanagedType.LPTStr)] 
      public string Title; 
      public uint X; 
      public uint Y; 
      public uint XSize; 
      public uint YSize; 
      public uint XCountChars; 
      public uint YCountChars; 
      public uint FillAttribute; 
      public uint Flags; 
      public ushort ShowWindow; 
      public ushort Reserverd2; 
      public byte bReserverd2; 
      public IntPtr StdInput; 
      public IntPtr StdOutput; 
      public IntPtr StdError; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     struct PROCESS_INFORMATION 
     { 
      public IntPtr Process; 
      public IntPtr Thread; 
      public uint ProcessId; 
      public uint ThreadId; 
     } 

     [DllImport("advapi32.dll", SetLastError = true)] 
     static extern bool InitializeSecurityDescriptor(IntPtr pSecurityDescriptor, uint dwRevision); 
     const uint SECURITY_DESCRIPTOR_REVISION = 1; 

     [DllImport("advapi32.dll", SetLastError = true)] 
     static extern bool SetSecurityDescriptorDacl(ref SECURITY_DESCRIPTOR sd, bool daclPresent, IntPtr dacl, bool daclDefaulted); 

     [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     extern static bool DuplicateTokenEx(
      IntPtr hExistingToken, 
      uint dwDesiredAccess, 
      ref SECURITY_ATTRIBUTES lpTokenAttributes, 
      SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, 
      TOKEN_TYPE TokenType, 
      out IntPtr phNewToken); 

     [DllImport("advapi32.dll", SetLastError = true)] 
     public static extern bool LogonUser(
      string lpszUsername, 
      string lpszDomain, 
      string lpszPassword, 
      int dwLogonType, 
      int dwLogonProvider, 
      out IntPtr phToken 
      ); 

     [DllImport("advapi32.dll", SetLastError = true)] 
     static extern bool GetTokenInformation(
      IntPtr TokenHandle, 
      TOKEN_INFORMATION_CLASS TokenInformationClass, 
      IntPtr TokenInformation, 
      int TokenInformationLength, 
      out int ReturnLength 
      ); 

     [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
     static extern bool CreateProcessAsUser(
      IntPtr Token, 
      [MarshalAs(UnmanagedType.LPTStr)] string ApplicationName, 
      [MarshalAs(UnmanagedType.LPTStr)] string CommandLine, 
      ref SECURITY_ATTRIBUTES ProcessAttributes, 
      ref SECURITY_ATTRIBUTES ThreadAttributes, 
      bool InheritHandles, 
      uint CreationFlags, 
      IntPtr Environment, 
      [MarshalAs(UnmanagedType.LPTStr)] string CurrentDirectory, 
      ref STARTUPINFO StartupInfo, 
      out PROCESS_INFORMATION ProcessInformation); 

     [DllImport("Kernel32.dll")] 
     extern static int CloseHandle(IntPtr handle); 

     [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] 
     internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen); 

     [DllImport("advapi32.dll", SetLastError = true)] 
     internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); 

     [StructLayout(LayoutKind.Sequential, Pack = 1)] 
     internal struct TokPriv1Luid 
     { 
      public int Count; 
      public long Luid; 
      public int Attr; 
     } 

     internal const int SE_PRIVILEGE_ENABLED = 0x00000002; 
     internal const int TOKEN_QUERY = 0x00000008; 
     internal const int TOKEN_DUPLICATE = 0x0002; 
     internal const int TOKEN_ASSIGN_PRIMARY = 0x0001; 

     #endregion 

     public static bool LoginUser(string domain, string username, string password, string program, string workingDir) 
     { 
      IntPtr token = IntPtr.Zero; 
      IntPtr primaryToken = IntPtr.Zero; 

      try 
      { 
       bool result = LogonUser(username, domain, password, (int)LOGON_TYPE.LOGON32_LOGON_NETWORK, (int)LOGON_PROVIDER.LOGON32_PROVIDER_DEFAULT, out token); 
       if (!result) 
       { 
        int winError = Marshal.GetLastWin32Error(); 
        Console.WriteLine("LoginUser unable to login user " + username + ", error: " + winError); 
        return false; 
       } 

       SECURITY_ATTRIBUTES processAttributes = new SECURITY_ATTRIBUTES(); 
       SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR(); 
       IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(sd)); 
       Marshal.StructureToPtr(sd, ptr, false); 
       InitializeSecurityDescriptor(ptr, SECURITY_DESCRIPTOR_REVISION); 
       sd = (SECURITY_DESCRIPTOR)Marshal.PtrToStructure(ptr, typeof(SECURITY_DESCRIPTOR)); 

       result = SetSecurityDescriptorDacl(ref sd, true, IntPtr.Zero, false); 
       if (!result) 
       { 
        int winError = Marshal.GetLastWin32Error(); 
       } 

       primaryToken = new IntPtr(); 
       result = DuplicateTokenEx(token, 0, ref processAttributes, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenPrimary, out primaryToken); 
       if (!result) 
       { 
        int winError = Marshal.GetLastWin32Error(); 
       } 

       processAttributes.SecurityDescriptor = ptr; 
       processAttributes.Length = (uint)Marshal.SizeOf(sd); 
       processAttributes.InheritHandle = true; 

       SECURITY_ATTRIBUTES threadAttributes = new SECURITY_ATTRIBUTES(); 
       threadAttributes.SecurityDescriptor = IntPtr.Zero; 
       threadAttributes.Length = 0; 
       threadAttributes.InheritHandle = false; 

       bool inheritHandles = true; 
       IntPtr environment = IntPtr.Zero; 

       STARTUPINFO startupInfo = new STARTUPINFO(); 
       startupInfo.Desktop = ""; 

       PROCESS_INFORMATION processInformation; 

       result = CreateProcessAsUser(
        primaryToken, 
        program, 
        program, 
        ref processAttributes, 
        ref threadAttributes, 
        inheritHandles, 
        16, 
        environment, 
        workingDir, 
        ref startupInfo, 
        out processInformation); 

       if (!result) 
       { 
        int winError = Marshal.GetLastWin32Error(); 
        Console.WriteLine("LoginUser unable to create process as user " + username + ", error: " + winError); 
        return false; 
       } 

       return true; 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine("LoginUser exception encountered: " + e.Message()); 
       return false; 
      } 
      finally 
      { 
       if (token != IntPtr.Zero) 
       { 
        int x = CloseHandle(token); 
        if (x == 0) 
         throw new Win32Exception(Marshal.GetLastWin32Error()); 
        x = CloseHandle(primaryToken); 
        if (x == 0) 
         throw new Win32Exception(Marshal.GetLastWin32Error()); 
       } 
      } 
     } 

     public static SecureString securePassword(string password) 
     { 
      if (string_null(password)) return null; 
      SecureString secure = new SecureString(); 
      foreach (char c in password) 
      { 
       secure.AppendChar(c); 
      } 
      return secure; 
     } 
    } 
} 

Và mục tiêu của tôi là để có thể gọi nó đơn giản là:

if (!LoginUser("machinename", "username", "password", "c:\\path\\to\\program.exe", "c:\\path\\to")) 
{ 
    // error 
} 
else 
{ 
    // success, user is logged into desktop and app is launch 
    // as user with desktop access 
} 

Trả lời

3

tôi đã có kịch bản tương tự trước và nhận được những điều phức tạp vì vậy tôi chỉ sử dụng PSEXEC kết hợp với Process.Start

Chỉ cần sử dụng PSEXEC như whats ghi trên mẫu của họ tất cả các bạn phải làm là một cái gì đó giống như

Sao chép này hoặc cài đặt thực thi của bạn thông qua cá tuyết e hoặc thủ công (tức là program.exe) với hệ thống từ xa và thực hiện nó một cách tương tác, chạy dưới DannyGlover tài khoản:

psexec \\workstation64 -c program.exe -u YourUser -p YourPa55w0rd 

Bây giờ bạn biết các thông số của bạn thì bạn có thể sử dụng Process.Start để chạy nó. Vì vậy, nó sẽ giống như thế này

using System.Diagnostics; 
... 
Process process = new Process(); 
process.StartInfo.FileName = "program.exe"; 
process.StartInfo.Arguments = "\\workstation64 -c program.exe -u YourUser -p YourPa55w0rd"; 
process.Start(); 
process.WaitForExit(); 

Bởi theo cách bạn có thể tìm hiểu thêm và tải PSEXEC đây http://ss64.com/nt/psexec.html

+0

Hi Raymund, điều này có thực sự ghi lại người dùng YourUser vào màn hình nền và khởi chạy ứng dụng không? – joelc

+1

Nó sẽ không thể chất nhưng nó sẽ chạy các ứng dụng trên máy tính để bàn/máy trạm bạn đang đề cập như người dùng mà bạn chỉ định. Tôi đã sử dụng rất nhiều điều này trên kịch bản của chúng tôi, nơi chúng tôi có các máy chủ trên hơn 200 cửa hàng nơi chúng tôi cần phân phối tệp thực thi và chạy nó như một người dùng nhất định – Raymund

+0

Cảm ơn, vấn đề là ứng dụng tôi cần chạy thay mặt người dùng đang sử dụng các dịch vụ yêu cầu tài khoản có quyền truy cập máy tính để bàn, vì vậy điều này sẽ không hoạt động. – joelc

0

tôi thấy vấn đề của bạn trên Elance.com và tìm thấy liên kết này.

Tôi đã có cùng một loại vấn đề với một trong các dự án của tôi. Điều đó yêu cầu dịch vụ windows để khởi chạy một thiết bị đầu cuối giao tiếp POS Terminal và phải có giao diện người dùng có quyền truy cập quản trị viên. Tôi đã thử mạo danh của winlogon.exe để tránh UAC nhưng điều đó không giúp được gì.

Đối với sự cố của tôi, tôi đã sử dụng Tác vụ theo lịch và đã tạo tác vụ của mình bằng C#. Bạn có thể tìm thấy một thư viện rất tốt ở đây http://taskscheduler.codeplex.com. Bây giờ trên một cuộc gọi yêu cầu, bạn có thể chạy nhiệm vụ động và bạn có toàn quyền kiểm soát điều đó.

Bạn có thể tạo công việc của riêng bạn/chỉnh sửa/xóa động và có thể chạy các ứng dụng của bạn bằng cách không tránh UAC.

0

Bạn đang tìm cách tạo phiên tương tác mới. Thật không may, điều này là không thể. Theo tôi hiểu, bạn muốn khởi chạy một quá trình và sau đó điều khiển máy từ xa với VNC. Có lẽ bạn chỉ cần sử dụng Remote Desktop?

+0

Hi Codeguard, về mặt kỹ thuật có thể là nhiều kiốt đã xây dựng các nhà cung cấp xác thực của riêng họ để làm chính xác điều này và tôi đang tìm cách làm điều đó trong ứng dụng của riêng tôi. Vì lý do tôi không thể đi vào đây, nó phải được thực hiện theo chương trình mà không cho phép người dùng xem hoặc tương tác trực tiếp với màn hình đăng nhập. – joelc

Các vấn đề liên quan