Announcement

Collapse
No announcement yet.

Problem mit ASP und SQL-Server und Trusted Connection

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem mit ASP und SQL-Server und Trusted Connection

    Hallo Forum,

    hoffentlich kann mir hier jemand helfen! Ich habe folgendes Problem:

    ich möchte eine ASP.NET-Anwendung erstellen, die per Trusted Connection eine Verbindung zu einem SQL-Server aufbaut. Es soll also die UserID des am Client angemeldeten NT-User (Die User sind auf einem Domäne-Server) benutzt werden und über den IIS (5.0) und ASP.NET / ADO.NET mit folgendem Connectionstring eine Verbindung aufgebaut werden:

    "data source=xxxxx;initial catalog=Intranet;trusted_connection =yes"

    In der Datei WEB.CONFIG habe ich den folgenden Eintrag erstellt:

    <identity impersonate="true"/>

    damit das WEB entsprechend konfiguriert ist, im IIS habe ich nur die Windows-Authentifizierung für das Web aktiviert (anonyme Anmeldung ist deaktiviert).

    Das ganze funktioniert auch wunderbar, solange Internetserver und SQL-Server auf der gleichen Maschine laufen. Sobald ich aber den Servernamen im Connectionstring auf einen SQL-Server auf den Namen einer anderen Maschine (gleiche Konfiguration, Windows-Sicherheit ist im SQL-Server eingeschaltet)ändere bekomme ich ein Fehlermeldung : "Anmeldung für Benutzer \ fehlgeschlagen".

    Kennt jemand eine Lösung für das Problem? Ist doch eigentlich eine Standardkonfiguration (wird ja in jedem VB-Buch beschrieben, nur leider gibt es entweder ein theoretisches Beispiel zur Lastverteilung durch Einsatz verschiedener Maschinen oder ein Beispiel zur Trusted Connection aber immer nur für (localhost), die Kombination gibts nirgends!!!)

    Vielen Dank für eure Hilfe!!
    Gruß

    Thomas Hempeler

  • #2
    Hallo,

    tritt das Problem auch bei der folgenden Web.config auf?
    <pre>
    <configuration>
    <system.web>
    <authentication mode="Windows" />
    <identity impersonate="true" />
    <authorization>
    <allow users="*">
    <deny users="?" />
    </authorization>
    </system.web>
    </configuration>
    </pre>
    Wenn ja, was liefert die folgende Prüfung zurück, wenn der Anwender die Seite aufruft?
    <pre>
    private void Page_Load(object sender, System.EventArgs e)
    {
    if (User.Identity.IsAuthenticated)
    {
    this.Label3.Text = "Authenticated: " + User.Identity.Name;
    }
    else
    {
    this.Label3.Text = "Nicht Authenticated";
    }
    }
    </pre>
    Gehören die Rechner für den Web-Server (ASP.NET) und den SQL-Server zur gleichen Domäne, an der auch die User angemeldet sind

    Comment


    • #3
      Hallo,

      meine Web-Config Datei sieht genau so aus wie oben beschrieben. Mit der Methode User.Identity.Name bekomme ich auch die richtige UserID angezeigt.

      Das Durchreichen der UserID klappt ja auch, wenn beider Server auf einer Maschine installiert sind. Das Problem muss also beim weiterreichen der UserID an den entfernten Server durch die ASP-Engine liegen. Bei einer Windows-Forms funktionert es übrigens auch wunderbar.

      Beide Server sind in der selben Domäne angemeldet

      Comment


      • #4
        Hallo,

        in der Theorie sollte das im Idealfall eigentlich auch funktionieren: Wenn der IIS einen Request-Aufruf auf eine Ressource erhält, die für ASP.NET registriert ist (wie zum Beispiel im Fall einer ASPX-Datei), so wird dieser Aufruf an die ISAPI-DLL <i>aspnet_isapi.dll</i> weitergeleitet. Diese DLL läuft im gleichen Prozess wie der IIS selbst (also in <i>inetinfo.exe</i>). Eine ASP.NET-Anwendung des IIS 5.x (der neue 6.0 arbeitet anders!) wird jedoch in einem separaten Prozess (<i>aspnet_wp.exe</i>) ausgeführt, daher muss die ISAPI-DLL den Aufruf über eine <i>Namep Pipe</i> an den ASP.NET-Prozess weiterleiten, wobei diese Instanz des Workerprozesses vorher über <i>LogonUser</i> und <i>CreateProcessAsUser</i> unter dem festgelegten Benutzerkonto ausgeführt wird, das in der Konfigurationsdatei <i>machine.config</i> (Framework-Unterverzeichnis von Windows) vom Eintrag <i>processModel</i> festgelegt wird. Innerhalb des ASP.NET-Prozesses schotten verschiedene Application Domains (AppDomain) die ASP.NET-Anwendungen voneinerander ab. Wenn <i>aspnet_isapi.dll</i> den Request-Aufruf an <i>aspnet_wp.exe</i> weiterleitet, überträgt es auch den vom IIS erhaltenen Access Token an ASP.NET. Dieser Access Token sieht je nach Konfiguration unterschiedlich aus:<br>
        a) Anonymer Zugriff im IIS erlaubt: <i>ISUR_machinename</i> <br>
        b) Authentifizierter Zugriff im IIS erzwungen: <i>Benutzername</i> <br>
        Bevor ASP.NET diesen Request-Aufruf weiterverarbeitet, wird zuerst geprüft, ob das erhaltene Access Token für die angeforderte Ressource die ACL Authorization (Zugriffsprüfung durch das NTFS-Dateisystem) besteht. ASP.NET arbeitet diese Prüfung in jedem Fall ab, auch wenn die ASP.NET-Anwendung die Impersonation aktiviert hat. War diese Prüfung erfolgreich, so wird das Access Token der ASP.NET-Anwendung zur Verfügung gestellt, so dass die Anwendung über die Impersonation eine benutzerabhängige Zugriffsberechtigung nutzen kann.

        Um die Ursache für dieses Problem einzukreisen, könnte man den folgenden Test machen: Eine ASP.NET-Seite (ohne Impersonation) arbeitet die Schritte in eigener Regie ab, indem sie selbst LogonUser aufruft und das Ergebnis über 5 Label-Instanzen im Web Form zurückliefert: Die Anzeige sollte dabei von Rechnername\ASPNET auf Rechnername\NeuerBenutzername wechseln. Allerdings wird auch das letztendlich auch <b>nicht</b> so wie anfangs geplant funktionieren (Grund dafür siehe unten):<pre>
        Imports System.Security.Principal
        Imports System.Runtime.InteropServices
        Imports System.Data.SqlClient
        ..
        <DllImport("advapi32.dll")> _
        Public Shared Function LogonUser(ByVal lpszUsername As String, ByVal lpszDomain As String, ByVal lpszPassword As String, _
        ByVal dwLogonType As Integer, ByVal dwLogonProvider As Integer, ByRef phToken As Integer) As Boolean
        End Function

        <DllImport("Kernel32.dll")> _
        Public Shared Function GetLastError() As Integer
        End Function

        Private sNewUserName As String = "Benutzername"
        Private sNewUserDomain As String = "Servername"
        Private sNewUserPasswd As String = "Benutzerpasswort"

        Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' Default-Zustand anzeigen: Rechnername\ASPNET
        Me.Label1.Text = System.Security.Principal.WindowsIdentity.GetCurre nt().Name
        ' LogonUser = anderers Benutzerkonto aktivieren
        Dim iLUToken As Integer
        Dim bLoggedOn As Boolean = LogonUser(sNewUserName, sNewUserDomain, sNewUserPasswd, 3, 0, iLUToken)
        Dim iLastError As Integer = GetLastError()
        If ((iLastError <> 0) AndAlso (iLastError <> 126)) Then
        Me.Label2.Text = iLastError.ToString()
        Else
        Me.Label2.Text = "Logon User war erfolgreich: " + bLoggedOn.ToString()
        End If
        ' Impersonate
        Dim aWIToken As IntPtr = New IntPtr(iLUToken)
        Dim aNewWI As WindowsIdentity = New WindowsIdentity(aWIToken)
        Dim aNewWIC As WindowsImpersonationContext = aNewWI.Impersonate()
        ' Erfolg anzeigen: Rechnername\NeuerBenutzername
        Me.Label3.Text = System.Security.Principal.WindowsIdentity.GetCurre nt().Name
        '
        Dim strConn As String = "data source=ServerName;initial catalog=Northwind;integrated security=SSPI;"
        Dim aCon As New SqlConnection(strConn)
        Dim aCmd As New SqlCommand("SELECT CompanyName FROM Customers WHERE CustomerID = 'FRANK'", aCon)
        Dim aDR As SqlDataReader
        aCon.Open()
        Try
        aDR = aCmd.ExecuteReader()
        aDR.Read()
        Me.Label5.Text = aDR(0).ToString()
        Finally
        aDR.Close()
        aCon.Close()
        End Try
        ' Impersonate rückgängig machen
        aNewWIC.Undo()
        ' Erfolg anzeigen: Rechnername\ASPNET
        Me.Label4.Text = System.Security.Principal.WindowsIdentity.GetCurre nt().Name
        End Sub
        </pre>
        Wenn dieser Test des direkten Logons auch nicht zum Ziel führt, müssen wir vermutlich das Kleingedruckte nochmals gründlicher durcharbeiten. Auf der Hilfeseite <i>IIS Authentication</i> der .NET Framework-Hilfe ist der folgende Satz zu finden: "<i>When used in conjunction with <b>Kerberos v5 authentication</b>, IIS can <b>delegate security credentials among computers</b> running Windows 2000 and later that are <b>trusted for delegation</b>. Delegation enables <b>remote access</b> of resources on behalf of the delegated user. </i>". Bisher habe ich selbst auf die Impersonation für den MS SQL Server verzichtet, das dies zum einen Rechnenzeit kostet und zum anderen auch den automatischen Datenbankverbindungs-Pool ausbremst.

        Im dem über die URL http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/authaspdotnet.asp verfügbaren Microsoft-Papier ist die folgende Einschränkung für Integrated Windows Authentication zu finden: "<i>The NTLM protocol does <b>not</b> support delegation. After the client's credentials are passed to the IIS server, they <b>cannot be passed to a back-end server for authentication</b>. However, Kerberos supports delegation, which allows the client credentials to be delegated to other processes on multiple downstream computers. For example, you can use Kerberos to present a Web user's credentials to a COM+ middle tier and through to a Microsoft SQL Server™ database, configured with Windows Integrated Security. Kerberos authentication is not enabled in a default Active Directory configuration. You must ensure your environment will support Kerberos before depending on it as a delegation solution.</i>".

        Fazit: Die Theorie funktioniert anscheinend erst dann in der Praxis, wenn man den Weg der Standardkonfiguration des IIS 5 verlässt und zu Kerberos wechselt.

        &#10

        Comment


        • #5
          Leider komme ich immer noch nicht klar. Wie aktiviere ich denn Kerberos? Kann ich das für meinen Server machen oder muss das auf dem Domänenserver aktiviert werden? Leider kenne ich mich mit dem NT-Berechtigungskonzept zu wenig aus :-(

          Comment


          • #6
            &gt;Wie aktiviere ich denn Kerberos?

            Im Kleingedruckten steht, dass im Fall von NTLM die Rechte nicht auf einen dritten Rechner delegiert werden können. Um das zu nutzen, müssen alle beteiligten Rechner anstelle von NTLM zu Kerberos welchseln. In der Voreinstellung probieren alle Windows 2000-Clients bereits die Authentifizierung beim AD über Kerberos - antwortet das Active Directory darauf jedoch nicht, machen die Windows 2000-Clients einen Fallback zu NTLM. Werden Windows 9x-/Me-/NT4-Client eingesetzt, steht Kerberos nicht zur Verfügung.

            Wird auf einem Windows 2000 Server ein Active Directory installiert, so kommt automatisch auch ein <i>Kerberos Key Distribution Center</i> (KDC) auf den Server. Der KDC muss dann nur noch aktiviert werden (Default Domain Policy | Computer Configuration | Windows Settings | Security Settings | <i>Kerberos Policy</i>) und die jeweiligen Benutzerkonten muss als "Vertrauenswürdig" markiert werden (Properties | Account | <i>Account ist trusted for delegation</i>)

            Comment


            • #7
              Hallo Herr Hempeler,
              ich habe das gleiche Problem unter NT.
              Haben Sie eine Lösung gefunden?
              Wenn ja, wäre ich sehr dankbar wenn Sie mir weiterhelfen können.

              Wenn ich mich direkt am IIS Server mit einem auf dem SQl Server eingetragenen User Account anmelde, kann ich von anderen Clients eine bestimmte Zeit lang die Datenbank abfragen.
              Nach ca. zwei Minuten ist dies nicht mehr möglich

              Comment


              • #8
                Leider bis heute noch nicht. Ich bin jetzt komplett auf SQL-Server Logins umgestiegen und prüfe ggf. Berechtigungen im Quellcode

                Comment

                Working...
                X