WernerK: sqlsrv_connect Connection could not be established

Hallo,

ich bin etwas am verzweifeln: Ich versuche schon ewig eine Verbindung mit PHP 7 und sqlsrv_connect zu einem SQL Server herzustellen.

$serverName = "myhost\myserver";
$connectionInfo = array( "Database"=>"myDB", "UID"=>"myuser", "PWD"=>"mypwd");
$conn = sqlsrv_connect( $serverName, $connectionInfo);

var_dump($conn);

if( $conn ) {
     echo "Connection established.<br />";
}else{
     echo "Connection could not be established.<br />";
     	 
	 var_dump(sqlsrv_errors());
	 
	 print_r( sqlsrv_errors(), true);
	 die();
}

Das einzige was kommt ist.

bool(false) Connection could not be established. NULL

In der php.ini ist php_sqlsrv.dll eingebunden: extension=php_sqlsrv.dll

ein Odcb Treiber wurde installiert. Auf den SQL Server komme ich mit den gleichen Credentials und mit Management Studio drauf.

Es handelt sich um einen Server 2012 R2 und PHP 7.0.27 x64

Bin für jeden Tipp dankbar.

Gruss

Werner

  1. Hallo,

    Bin für jeden Tipp dankbar.

    Hostname aufgelöst? Host erreichbar? Port blockiert? Eine zweckmäßige Fehlerbehandlung würde alle drei Fragen gleichzeitig mit einem Male beantworten 😉

    MfG

    1. Hallo,

      danke dir. also im CDM bekomme ich mit ping servername eine IP zurück. Und wie gesagt auf die DB komme ich mit Management Studio drauf. Der Default Port ist doch 1433 oder? Wenn ich mit SSMS drauf komme müsste es doch auch mit PHP gehen oder?

      Gruss Werner

    2. um nochmals auf deine Fragen zurückzukommen: Der Hostname wird aufgelöst und ist erreichbar. Ich konnte mit Telnet und Port 1433 eine Verbindung herstellen.

      Was kann man noch kontrollieren?

      Gruss Werner

      1. Hallo WernerK,

        nur so ein Verdacht: Sicherlich wird deine DB nicht myhost\myserver heißen, sondern anders.

        Ändere mal

        $servername = "myhost\myserver";
        

        in eine von den beiden nachfolgenden Zeilen:

        $servername = 'myhost\myserver';
        $servername = "myhost\\myserver";
        

        Backslash in einem double-quote String hat Sonderaufgaben. Insbesondere \n für Newline und \t für Tab.

        Rolf

        --
        sumpsi - posui - clusi
        1. Hallo Rolf B,

          $servername = 'myhost\myserver';
          $servername = "myhost\\myserver";
          

          $servername = 'myhost/myserver'; sollte doch auch gehen, oder?

          PS: In Codeblöcken kann man die Klassen bad resp. good gleich hintendran hängen.

          ~~~php, good
          PHP-Code

          
          Bis demnächst  
          Matthias
          
          -- 
          Rosen sind rot.
          
          1. Hallo Matthias,

            keine Ahnung ob / auch funktioniert, müsste ich ausprobieren. Mein SQL Server ist aber an C# gewöhnt, wenn ich den mit PHP anrede kriegt er 'nen Schreck und stürzt ab… (sprich: noch nie gemacht, keine Ahnung ob mein Spiel-PHP hier das überhaupt hinkriegt, keine Lust zum fummeln).

            Rolf

            --
            sumpsi - posui - clusi
        2. Hallo Rolf,

          danke dir. Ja an das habe ich auch schon gedacht.

          Mit zwei Backslashes habe ich es auch schon versucht. $servername = "myhost\myserver"; und auch nur mit "myserver" , also ohne Instanzname.

          Komisch ist halt, dass wenn ich absichtlich auch falsche Credentials eingebe, immer die gleiche Meldung kommt.

          Connection could not be established

          sqlsrv_errors() bringt ja auch nichts zurück.

          Als ob der Treiber nicht richtig angesprochen wird? Auf einem anderen Testsystem mit Win 10 und IIS und gleichem Script klappt die Verbindung.

          Der Server 2012 R2 ist wohl besonders gesichtert, aber dennoch sollte doch eine Verbindung mit sqlsrv_connect zum SQL Server funktionieren? PHP läuft als FastCGi, das IIS Handler Mapping wurde gemacht. Es gibt auch keine Fehlermeldungen im Windows Event.

          Bin wirklich ratlos.

          Gruss Werner

  2. Hallo zusammen,

    ich bin nun etwas weiter gekommen, bzw. weiss nun woran es liegt.

    Die Sqlsrv Verbindung klappt nur, wenn man im IIS Manager bei Anonymus Authentication auf "Application pool identity" stellt. Wenn man den Standard User "IUSER" nimmt, kommt wieder "Connection could not be established"

    Kann mir hier jemand sagen, welche Rechte der IUSER noch braucht? Ich habe ihm volle Rechte für das Verzeichnis C:\PHP gegeben. Muss er event auch auf das Windows\system32 zugreifen oder sonst wo?

    vielen Dank

    Gruss Werner

    1. hi,

      Kann mir hier jemand sagen, welche Rechte der IUSER noch braucht?

      Die Frage ist, ob Du die ODBC Datenquelle als System~ oder als UserDSN einrichtest.

      MfG

      1. Hi,

        momentan ist sie als System DSN eingerichtet. Die Frage ist aber: Muss man denn überhaupt eine DSN einrichten? Microsoft schreibt nur, dass der ODBC Treiber als Layer genutzt wird. Es steht aber nirgends etwas, dass man eine System DSN oder USEr DSN einrichten soll.

        Gruss Werner

        1. Hi,

          momentan ist sie als System DSN eingerichtet. Die Frage ist aber: Muss man denn überhaupt eine DSN einrichten? Microsoft schreibt nur, dass der ODBC Treiber als Layer genutzt wird. Es steht aber nirgends etwas, dass man eine System DSN oder USEr DSN einrichten soll.

          So isses. Entweder man verbindet sich mit der ODBC Datenquelle (lokal) oder direkt mit dem SQL Server (host, port). Beim Einrichten der ODBC hat man auch die Möglichkeit zum Testen der Verbindung. Was mit PHP möglich bzw. zweckmäßiger ist, kann ich jedoch nicht beurteilen.

          MfG

        2. Tach!

          momentan ist sie als System DSN eingerichtet. Die Frage ist aber: Muss man denn überhaupt eine DSN einrichten?

          Soweit ich das sehe, ist das nicht nötig.

          Microsoft schreibt nur, dass der ODBC Treiber als Layer genutzt wird. Es steht aber nirgends etwas, dass man eine System DSN oder USEr DSN einrichten soll.

          Die Beispiele sagen auch, dass man den Servernamen und nicht den Namen der DSN angeben soll. Also wird eine DSN nicht notwendig sein.

          dedlfix.

    2. Tach!

      Die Sqlsrv Verbindung klappt nur, wenn man im IIS Manager bei Anonymus Authentication auf "Application pool identity" stellt.

      Application pool identity ist nur ein Sammelbegriff, der konkrete Name ist "IIS AppPool\Name_des_ApplicationPools"

      Wenn man den Standard User "IUSER" nimmt, kommt wieder "Connection could not be established"

      Sieht nach einem Problem mit der Anmeldung aus. Als ob Windows Authentication verwendet wird, statt UID und PWD. Das PHP-Handbuch sagt, dass beim Vorhandensein von UID und PWD diese verwwendet werden und nicht die Windows Authentication. Eigentlich dürfte der User, unter dem der Application-Pool läuft, keine Rolle spielen. Ich kann mir da nur vorstellen, dass nicht die Verbindung sondern das Zugreifen auf lokale Ressourcen blockiert ist, die man für die Verbindung braucht. Aber das ist nur eine Idee, denn sowas ist mir noch nicht untergekommen. Mit PHP habe ich das auch noch nicht probiert, nur mit C# und .NET. Da verwendet man einen Connectionstring und mit dem geht es problemlos mit Windows Authentication oder konkretem User. Vorausgesetzt natürlich, dass die jeweils Rechte im SQL Server haben.

      Kann mir hier jemand sagen, welche Rechte der IUSER noch braucht? Ich habe ihm volle Rechte für das Verzeichnis C:\PHP gegeben.

      Wenn da die PHP-Installation liegt, braucht er nur Leserechte. Schreibrechte werden nur für die konfigurierten Temp- und Session-Verzeichnisse benötigt und überall da, wo du Dateien hinlegen lässt.

      Muss er event auch auf das Windows\system32 zugreifen oder sonst wo?

      Vermutlich für irgendwelche DLLs, aber das ist bereits mit Lesezugriff ausgestattet, wenn man in der Users-Gruppe ist.

      dedlfix.

      1. Hallo dedlfix,

        der Application-Pool User spielt so lange eine Rolle, wie man den per Web einfliegenden User nicht impersoniert. Impersonieren geht aber nur, wenn die Webrequests aus dem internen Netz kommen (d.h. gleiches AD) oder von außen Credentials mitliefern, die eine Impersonierung erlauben. Und dann muss man es erstmal TUN - weil das Auto-Impersonieren ist eigentlich ein ASP.NET Feature. Zumindest finde ich den Identitätswechsel-Schalter nur in den IIS-Webs, bei denen .NET im AppPool aktiviert ist.

        Der IUSER ist eigentlich ein komplett entrechteter User, der so gut wie nichts darf. Möglicherweise auch keine Netzwerkverbindungen aufbauen. Das könnte erklären, warum der SQL Server dann nicht erreichbar ist.

        Rolf

        --
        sumpsi - posui - clusi
        1. hi,

          Der IUSER ist eigentlich ein komplett entrechteter User, der so gut wie nichts darf. Möglicherweise auch keine Netzwerkverbindungen aufbauen. Das könnte erklären, warum der SQL Server dann nicht erreichbar ist.

          Eine zweckmäßige Fehlerbehandlung auch. In Perl's DBI Dokumentation wird extra darauf hingewiesen, daß man RaiseError bereits vor dem Aufbau einer Verbindung setzen sollte damit man sieht warum wenn eine Solche nicht zustandekommt.

          Das entspricht PHP's ERR_MODE EXCEPTION zumindest von der Sinngebung her.

          MfG

          1. Tach!

            Das entspricht PHP's ERR_MODE EXCEPTION zumindest von der Sinngebung her.

            Man sollte dazusagen, dass das keine generelle PHP-Geschichte ist, sondern auf PDO beschränkt.

            dedlfix.

          2. Tach!

            In Perl's DBI Dokumentation wird extra darauf hingewiesen, daß man RaiseError bereits vor dem Aufbau einer Verbindung setzen sollte damit man sieht warum wenn eine Solche nicht zustandekommt.

            Hat nur keine Relevanz für den vorliegenden Fall. Fehlermeldungen, die bei sqlsrv_connect() entstehen, müssen nachher mit sqlsrv_errors() ermittelt werden. Die werden nicht auf anderen Wegen ausgegeben.

            dedlfix.

            1. Tach!

              In Perl's DBI Dokumentation wird extra darauf hingewiesen, daß man RaiseError bereits vor dem Aufbau einer Verbindung setzen sollte damit man sieht warum wenn eine Solche nicht zustandekommt.

              Hat nur keine Relevanz für den vorliegenden Fall. Fehlermeldungen, die bei sqlsrv_connect() entstehen, müssen nachher mit sqlsrv_errors() ermittelt werden. Die werden nicht auf anderen Wegen ausgegeben.

              Doch, das gilt ja sinngemäß für PHP/PDO.

              Und: Die Alternative zur Funktion sqlsrv_connect() ist PDO.

              MfG