Frage

Hier ist mein Fenster / .NET-Sicherheits Stack:

  • Ein Windows-Dienst als Localsystem läuft auf einem Windows Server 2003-Box.
  • A .NET 3.5-Website auf dem gleichen Feld ausgeführt wird, unter "default" Produktions-Server IIS-Einstellungen (also wahrscheinlich als NETZWERK Benutzer?)

Auf meinem Standard VS2008 DEV-Umgebung Ich habe diese eine Methode, die von der ASP.NET app aufgerufen wird, der gut arbeitet:

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

Wenn ich dies auf dem Produktionsserver laufen, erhalte ich die folgende Fehlermeldung aus dem Servicecontroller:

  

Quelle: System.ServiceProcess ->   System.ServiceProcess.ServiceController -> IntPtr   GetServiceHandle (Int32) -> System.InvalidOperationException Nachricht:   Kann nicht eTimeSheetReminderService Dienst auf dem Computer öffnen ''.

Warum ist das passiert, und wie kann ich das Problem beheben?

EDIT:

Die Antwort ist unten, vor allem in den Kommentaren, aber zu klären:

  1. Die Frage wurde sicherheitsbezogene und trat auf, weil das NETZWERKDIENST-Konto nicht über ausreichende Rechte haben Sie auf Start / Stop a Service
  2. Ich habe ein lokales Benutzerkonto, und fügte hinzu, um es in die Benutzergruppe an (diese Gruppe hat fast Admin-Rechte)
  3. Ich will nicht meine ganze Web-Anwendung, die Benutzer die ganze Zeit zu imitieren, so dass ich nur Identitätswechsel in dem Verfahren, in dem ich den Dienst manipulieren. Ich tue dies, indem Sie die folgenden Ressourcen mich in Code zu helfen zu tun:

MS KB-Artikel und dies, nur um ein besseres Verständnis zu bekommen

Hinweis: Ich Identitätswechsel nicht über die web.config, das tue ich es im Code. Sehen Sie sich die MS KB Artikel oben.

War es hilfreich?

Lösung

Versuchen Sie, diese zu Ihrem Web.Config.

<identity impersonate="true"/>

Andere Tipps

Berechtigung zu erteilen, IIS zu starten / einen bestimmten Dienst stoppen:

  • Herunterladen und Installieren von Subinacl.exe . ( Achten Sie darauf, die neueste Version bekommen! Frühere Versionen in einigen Resource Kits verteilt funktionieren nicht! )
  • Geben Sie einen Befehl ähnlich: subinacl /service {yourServiceName} /grant=IIS_WPG=F

Dies gewährt Full-Service-Kontrollrechte für diesen besonderen Dienst an die integrierten in Gruppe IIS_WPG. (Dies funktioniert für IIS6 / Win2k3.) YMMV für neuere Versionen von IIS).

Das war eine gute Frage, die mich auch fasziniert ...

So, hier ist was ich getan habe, dieses Problem zu lösen:

  • Schritt 1:. Erstellen Sie ein Windows-Benutzerkonto auf dem lokalen Rechner mit minimalen Rechten
  • Schritt 2: Geben Sie diese Benutzerrechte den Dienst über subinacl.exe zu starten und stoppen
  • d. subinacl.exe / service WindowsServiceName / GRANT = PCNAME \ Testuser = STOE
  • Dowload von: http://www.microsoft.com /en-za/download/details.aspx?id=23510
  • Schritt 3: Verwenden Sie Identitätswechsel die Verwendung in Schritt 1 erstellt zu imitieren, den Dienst zu starten und stoppen

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

Update für IIS 8 (und vielleicht noch einige etwas älteren Versionen)

Die Benutzergruppe IIS_WPG existiert nicht mehr. Hat sich geändert IIS_IUSRS .

Auch starten Dienst beendet es nicht neccesary ist voll Berechtigungen (F) zu geben. Berechtigungen zum Starten, Stoppen und einen Service (TOP) pausieren sollten ausreichen. Als solche der Befehl sein sollte:

  

subinacl / service {yourServiceName} / gewähren = IIS_IUSRS = TOP

Beachten Sie, dass Sie die Eingabeaufforderung verweisen müssen (vorzugsweise als Administrator ausführen erhöht) Ordner C:\Windows\System32 bevor dieser Befehl ausgeführt wird.

Vergewissern Sie sich auch, dass Sie die subinacl.exe Datei kopiert haben, aus dem Installationsverzeichnis C:\Windows\System32, wenn ein Fehler ist.

Nur eine Vermutung, aber es scheint mir nicht der Fehler unbedingt auf die Sicherheit in Zusammenhang steht. Haben Sie den Dienst mit dem gleichen Namen auf dem Produktionsserver geben?

Wenn Sie Ihre Web-Anwendung, die Datenbank und Windows-Dienst hat darauf zugreifen kann, können Sie einfach die Flagge in der DB nutzen den Dienst neu zu starten. Im Service können Sie dieses Kennzeichen lesen und neu starten, wenn nicht besetzt usw. Nur für den Fall, wenn Sie den Code des Dienstes ändern.        Wenn es Dritter Service ist können Sie Ihren eigenen Windows-Dienst erstellen und Datenbank-Konfiguration verwenden, um zu steuern (Neustart) Dienste. Es ist der sichere Weg, und gibt Ihnen viel mehr Flexibilität und Sicherheit.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top