2009-05-04 24 views
14

Dưới đây là của tôi Windows/.NET an ninh ngăn xếp:Làm thế nào để Bắt đầu/Dừng một dịch vụ Windows từ một ứng dụng ASP.NET - An ninh phát

  • Một dịch vụ Windows chạy như LocalSystem trên Windows Server 2003 hộp.
  • Một Website .NET 3.5 chạy trên cùng một hộp, dưới "mặc định" sản xuất máy chủ IIS cài đặt (như vậy có lẽ là NETWORKSERVICE sử dụng?)

Về môi trường VS2008 DEV mặc định của tôi, tôi có một phương pháp này, mà được gọi từ ứng dụng ASP.NET, mà hoạt động tốt:

private static void StopStartReminderService() { 

    ServiceController svcController = new ServiceController("eTimeSheetReminderService"); 

    if (svcController != null) { 
     try { 
      svcController.Stop(); 
      svcController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10)); 
      svcController.Start(); 
     } catch (Exception ex) { 
      General.ErrorHandling.LogError(ex); 
     } 
    } 
} 

Khi tôi chạy trên các máy chủ sản xuất, tôi nhận được lỗi sau từ ServiceController:

Sourc e: System.ServiceProcess -> System.ServiceProcess.ServiceController -> IntPtr GetServiceHandle (Int32) -> System.InvalidOperationException Message: Không thể mở dịch vụ eTimeSheetReminderService trên máy tính '.'.

Tại sao điều này xảy ra và cách khắc phục sự cố?

EDIT:

Câu trả lời là bên dưới, chủ yếu là trong các ý kiến, nhưng để làm rõ:

  1. Vấn đề này có liên quan an ninh, và xảy ra do tài khoản NETWORKSERVICE không có đủ quyền để Bắt đầu/Dừng dịch vụ
  2. Tôi đã tạo Tài khoản người dùng cục bộ và thêm nó vào nhóm PowerUsers (nhóm này có quyền quản trị)
  3. Tôi không muốn toàn bộ Web App của tôi để mạo danh người dùng đó mọi lúc, vì vậy tôi mạo danh chỉ trong phương thức mà tôi thao tác dịch vụ. Tôi làm điều này bằng cách sử dụng các nguồn lực sau đây để giúp tôi làm điều đó trong mã:

MS KB articlethis, just to get a better understanding

LƯU Ý: Tôi không mạo danh thông qua web.config, tôi làm điều đó trong mã. Xem MS KB Article ở trên.

+0

Loại ngoại lệ nào? Một 'System.InvalidOperationException'? – Phaedrus

+0

@Phaedrus: vâng, vâng, đúng vậy. Tôi đã thêm một số thông tin lỗi trong bản chỉnh sửa của mình. cổ vũ – andy

Trả lời

6

Thử thêm tệp này vào Web.Config của bạn.

<identity impersonate="true"/> 
+0

hey phaedrus, lỗi tương tự – andy

+0

Truy cập vô danh có được bật trong IIS không? – Phaedrus

+0

yep, "Bật truy cập ẩn danh" được đánh dấu là – andy

0

Chỉ là linh cảm, nhưng nó không xuất hiện với tôi, lỗi nhất thiết liên quan đến bảo mật. Bạn đã cung cấp dịch vụ cùng tên trên máy chủ sản xuất chưa?

+0

@cdonner: vâng, tôi cũng nghi ngờ điều đó, nhưng không biết làm thế nào tôi có thể kiểm tra nó? Có, tên là như nhau, được định nghĩa trong mã, trong thành phần ServiceInstaller. Bất kỳ ý tưởng về cách tôi có thể nhận được một câu trả lời rõ ràng về việc nó thậm chí là an ninh? cổ vũ – andy

+0

bạn có thể khởi động và dừng nó khỏi dòng lệnh bằng cách sử dụng NET START/STOP không? – cdonner

+0

hey người đàn ông, vâng, chạy "NET START eTimeSheetReminderService" trong dấu nhắc lệnh bắt đầu dịch vụ thành công – andy

12

Để cho phép IIS để bắt đầu/dừng một dịch vụ cụ thể:

  • Tải về và cài đặt Subinacl.exe. ( Hãy chắc chắn để có được phiên bản mới nhất! Các phiên bản trước đó được phân phối trong một số bộ tài nguyên không hoạt động!)
  • Issue một lệnh tương tự như: subinacl /service {yourServiceName} /grant=IIS_WPG=F

này cấp quyền kiểm soát dịch vụ trọn gói cho rằng dịch vụ cụ thể cho nhóm built-in IIS_WPG. (Điều này làm việc cho IIS6/Win2k3.) YMMV cho các phiên bản mới hơn của IIS)

+0

Hoàn hảo, đã làm cho các trick cho tôi và tôi thậm chí không có thêm mạo danh để web.config của tôi. Chúc mừng! – Nabster

+0

Đây là giải pháp tốt hơn theo ý kiến ​​của tôi. Cảm ơn Martin_ATS. – amiir

+0

Sử dụng công cụ này để cấp cho người dùng quyền, theo đó bạn sử dụng mạo danh để mạo danh người dùng có quyền bắt đầu và ngừng dịch vụ. – 130nk3r5

1

Đây là một câu hỏi hay mà hấp dẫn tôi cũng ...

Vì vậy, đây là những gì tôi đã làm để giải quyết vấn đề này:.

  • Bước 1: Tạo tài khoản người dùng Windows trên máy cục bộ với các quyền tối thiểu.
  • Bước 2: Cung cấp cho người dùng này quyền để bắt đầu và dừng dịch vụ qua subinacl.exe
  • tức subinacl.exe/dịch vụ WindowsServiceName/CẤP = PCNAME \ TestUser = STOE
  • Dowload từ: http://www.microsoft.com/en-za/download/details.aspx?id=23510
  • Bước 3: sử dụng mạo danh để mạo danh sử dụng tạo ra ở bước 1 để bắt đầu và ngừng Dịch vụ

    public const int LOGON32_PROVIDER_DEFAULT = 0; 
    
    WindowsImpersonationContext _impersonationContext; 
    
    [DllImport("advapi32.dll")] 
    // ReSharper disable once MemberCanBePrivate.Global 
    public static extern int LogonUserA(String lpszUserName, 
        String lpszDomain, 
        String lpszPassword, 
        int dwLogonType, 
        int dwLogonProvider, 
        ref IntPtr phToken); 
    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    // ReSharper disable once MemberCanBePrivate.Global 
    public static extern int DuplicateToken(IntPtr hToken, 
        int impersonationLevel, 
        ref IntPtr hNewToken); 
    
    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    // ReSharper disable once MemberCanBePrivate.Global 
    public static extern bool RevertToSelf(); 
    
    [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 
    // ReSharper disable once MemberCanBePrivate.Global 
    public static extern bool CloseHandle(IntPtr handle); 
    
    private bool _impersonate; 
    
    public bool ImpersonateValidUser(String userName, String domain, String password) 
    { 
        IntPtr token = IntPtr.Zero; 
        IntPtr tokenDuplicate = IntPtr.Zero; 
    
        if (RevertToSelf()) 
        { 
         if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, 
          LOGON32_PROVIDER_DEFAULT, ref token) != 0) 
         { 
          if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) 
          { 
           var tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); 
           _impersonationContext = tempWindowsIdentity.Impersonate(); 
           if (_impersonationContext != null) 
           { 
            CloseHandle(token); 
            CloseHandle(tokenDuplicate); 
            _impersonate = true; 
            return true; 
           } 
          } 
         } 
        } 
        if (token != IntPtr.Zero) 
         CloseHandle(token); 
        if (tokenDuplicate != IntPtr.Zero) 
         CloseHandle(tokenDuplicate); 
        _impersonate = false; 
        return false; 
    } 
    
    #region Implementation of IDisposable 
    
    
    
    
    #endregion 
    
    #region Implementation of IDisposable 
    
    private void Dispose(bool dispose) 
    { 
        if (dispose) 
        { 
         if (_impersonate) 
          _impersonationContext.Undo(); 
         _impersonationContext.Dispose(); 
        } 
    } 
    
    public void Dispose() 
    { 
        Dispose(true); 
    } 
    #endregion 
    
    public static void StartStopService(bool startService, string serviceName) 
    { 
        using (var impersonateClass = new Impersonation()) 
        { 
         impersonateClass.ImpersonateValidUser(Settings.Default.LocalUsername, Settings.Default.Domain, Settings.Default.Password); 
         using (var sc = new ServiceController(serviceName)) 
         { 
          if (startService) 
           sc.Start(); 
          else if (sc.CanStop) 
           sc.Stop(); 
         } 
    
        } 
    } 
    
+0

LOGON32_LOGON_INTERACTIVE không hoạt động đối với tôi nhưng nhờ câu trả lời này https://stackoverflow.com/a/28503968/4568373 Tôi đã đổi nó thành LOGON32_LOGON_NETWORK và hoạt động tốt. –

0

Nếu ứng dụng web của bạn có cơ sở dữ liệu và cửa sổ dịch vụ có thể truy cập nó, bạn chỉ có thể sử dụng cờ trong DB để khởi động lại dịch vụ. Trong dịch vụ, bạn có thể đọc cờ này và khởi động lại nếu không bận vv Chỉ trong trường hợp nếu bạn có thể sửa đổi mã của dịch vụ. Nếu đó là dịch vụ bên thứ ba, bạn có thể tạo dịch vụ cửa sổ của riêng mình và sử dụng cấu hình cơ sở dữ liệu để kiểm soát (khởi động lại) các dịch vụ. Đó là cách an toàn và mang đến cho bạn sự linh hoạt và an toàn hơn nhiều.

1

Cập nhật cho IIS 8 (và có thể một số phiên bản nhẹ trước đó)

Các thuộc nhóm IIS_WPG không tồn tại nữa. Nó đã thay đổi thành IIS_IUSRS.

Ngoài ra, để bắt đầu dừng dịch vụ, không nhất thiết phải cấp quyền đầy đủ (F). Quyền để bắt đầu, dừng và tạm dừng một dịch vụ (TOP) là đủ. Như vậy lệnh nên là:

subinacl/dịch vụ {yourServiceName}/cấp = IIS_IUSRS = TOP

Lưu ý rằng bạn cần phải chỉ dấu nhắc lệnh (tốt nhất là nâng lên run as administrator) để C:\Windows\System32 Thư mục trước khi chạy lệnh này.

Cũng đảm bảo rằng bạn đã sao chép tệp subinacl.exe sang C:\Windows\System32 từ thư mục cài đặt nếu có lỗi.

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