dantegabriel
Goto Top

Problematik bei If abhängiger MYSQL Abfrage - und Ausgabewert

Hallo zusammen, ich habe ein Problem mit der dynamischen Ausgabe zweier Strings, wobei jeweils nur einer in Abhängigkeit von einer Varriablen angezeigt werden soll. Diese Varriable wird nach einer MYSQL DB Abfrage, in Abhängigkeit vom Ergebnis gesetzt. Naja ich hoffe ihr könnt mir da helfen, denn ich verstehe einfach den Fehler nicht. Doch nun erstmal der Reihe nach.

Hintergrund:
Ich arbeite an einem Loginsystem mit Zugriff auf 2 Datenbanken (1x Loginsystem selber auf Mysql Basis und nach erfolgreichem Login eine Suchfunktion die Daten in einer externen Postgresql Datenbank sucht und dann in einem Iframe anzeigt.) Das Loginsystem sowie das suchen nach den Daten in der ext. Datenbank funktioniert soweit tadellos. Da ich im nächsten Schritt aus Sicherheitsgründen eine manuelle aktivierung Seitens der Administration einbauen möchte, habe ich mich dazu entschieden dazu ein neues Feld in der Mysql Datenbank anzulegen. Dieses Feld befindet sich in der gleiben Tabelle wie auch alle anderen Userdaten (Name, PW usw.)) Nachdem ich nun bei meiner SQL Abfrage einen Zusatz hinzugefügt habe, der Abfragt ob der Wert im Feld Freischaltung (der Standartmäßig 0 ist) 1 ist oder nicht, kann sich ein Benutzer nur noch einloggen, wenn ein Administrator in der Datenbank zuvor den Wert von 0 auf 1 geändert hat.

Das Schwierige im letzten Teilschritt ist nun, das der User beim Anmeldeversuch nicht nur angegeben bekommt, das sein Name oder Passwort falsch eingegeben ist (sofern es falsch eingegeben ist) sondern auch, das der Account noch nicht freigeschaltet wurde.

Skripte:
nach dem sowohl der Username als auch das PW eingegeben wurde, werden die Daten via PHP in Varriablen gespeichert und dann weiterverarbeitet. Da der Seitenaufbau dynamisch gestaltet ist, habe ich dazu eine Funktion angelegt. Ich werde im nächsten Abschnitt weiter auf das Skript eingehen (und warum ich da was gemacht habe), hier soll erstmal nur das Skript zu sehen sein.

Die Funktion:
 
function login($username, $password, $db, $salt) {
	$password = hash('sha256', $password.$salt);  
	
	$sql = '  
		SELECT
			COUNT(*)
		FROM
			user
		WHERE
			Username = ?
		AND
			Password = ?
                AND
                        Freischaltung != 0                
			';	//Count (also zählen ob vorhanden geht schneller als expliziet den Wert auszulesen und zu prüfen.)  
	$stmt = $db->prepare($sql);
	$stmt->bind_param('ss', $username, $password);  
	$stmt->execute(); //ausführen
	$stmt->bind_result($result); //Ergebnis in einer Varriablen result speichern.
	$stmt->fetch(); //fetchen (speichern in "result") 
	$stmt->close();
        
    	if($result == 1) {
            $_SESSION['logged_in'] = true;  
            $_SESSION['username'] = $username;   
            return true; //Die Session muss noch an den Server geschickt werden
	} else {
	    $sql = '  
		SELECT
			COUNT(*)
		FROM
			user
		WHERE
			Username = ?
		AND
			Password = ?          
			';	//Count (also zählen ob vorhanden geht schneller als expliziet den Wert auszulesen und zu prüfen.)  
            $stmt = $db->prepare($sql);
            $stmt->bind_param('ss', $username, $password);  
            $stmt->execute(); //ausführen
            $stmt->bind_result($result); //Ergebnis in einer Varriablen result speichern.
            $stmt->fetch(); //fetchen (speichern in "result") 
            $stmt->close();
            if($result == 1) {
                $Fehlercode = 1;
            } else {
                $Fehlercode = 2;
            }
	}
}

Der dynamische Bezug:
if(login($_POST['username'], $_POST['password'], $db, $salt)) {  
	header('Location: /Script/login.php');	  
} else {
    if($Fehlercode == 1) {
        $error_msg = "Sie wurden noch nicht freigeschaltet. Bitte haben Sie noch etwas Gedult. ";           
    } else {
        $error_msg = "Der Benutzername oder das Passwort ist falsch. ";  
    }
}


Skript Beschreibung:
Es ist zugegeben vielleicht nicht die schönste Methode nach der SQL Abfrage eine weitere SQL Abfrage zu stellen, nur mit einem Parameter weniger (um die Art des fehler zu differenzieren), es ist jedoch der einzige Weg der mir eingefallen ist. Im ersten Schritt speichere ich den SQL Befehl in einer Varriablen, bereite dann die Datenbank auf das statement vor, übergebe nutzerspezifische Angaben mit bind_param, lasse dann die Abfrage durchführen und speichere das Ergebnis in einer Variablen. Unabhängig vom weiteren Verlauf des Skriptes und den Abfragen funktioniert das bis hierhin definitv.
Wenn das Ergebnis der Abfrage positiv ist, also alle abgefragten Inhalte einmal vorhanden sind (und es geht nur einmal da Benutzername unique ist) soll der Loginvorgang ganz normal von Statten gehen (Das Funktioniert). Wenn der Rückgabewert 0 ist, also mindestens eine der Abfragen nicht gefunden wurde, oder falsch ist soll weiter geprüft werden.

Das weiter Prüfen sieht so aus, das eine identische SQL Abfrage an den Server gesendet wird, jedoch ohne das auf die manuelle Freischaltung eingegangen wird. Ist dann bei dieser Abfrage etwas nicht in Ordnung, so ist das Passwort oder der Benutzername falsch bzw. nicht vorhanden. Trifft beides jedoch zu und es wird eine 1 zurückgegeben (Also die Angaben stimmen mit denen in der DB überein.) bleibt nur noch, das der Nutzer noch nicht freigeschaltet wurde. (Im Skript ist das mit Fehlercode 1 und Fehlercode 2 angegeben, wobei die entsprechende Fehlermeldung im dynamischen bezug steht. (Bzw. genauer in der Logik die alle Seiten verbindet.)

Problem:
Unabhängig davon was man falsch im Login eingibt, es erscheint immer nur der String $error_msg = "Der Benutzername oder das Passwort ist falsch. ". Aber ich verstehe nicht so ganz warum... (Wenn die Nutzerdaten stimmen funktioniert der Login und man kommt auf die nächste Seite bzw. diese wird dynamisch nachgeladen.)

Hardware:
Das Testsystem, auf dem ich die Skripte Teste besteht aus 2 virtuellen Apache Webservern (mit fester IP), auf dem einen ist eine Postgesql DB, auf dem anderen eine Mysql DB installiert. Auf der mysql DB liegen die Daten der Webseite. Genutzt werden alle erforderlichen Resourcen in der aktuellsten Version. (Also php, mysql server, postgresql server usw.) Falls ihr diesbezüglich noch weitere angaben benötigt, stelleich euch diese gerne zur Verfügung.

Schlosswort:
Ich hoffe ich konnte meine Problematik einigermaßen verständlich darlegen und vielleicht hat jemand eine Idee, was ich übersehen habe. Jedenfalls würde ich mich über eine Rückmeldung sehr freuen.

mfg: DanteGabriel

EDIT:
Der SQL Befehl
 $sql = '  
		SELECT
			Freischaltung
		FROM
			user
		WHERE
			Username = ?   
			';  
Mit entsprechender Anpassung des Skriptverlaufes führt zum gleichen Ergebnis bzw. Problem.

Content-ID: 179237

Url: https://administrator.de/contentid/179237

Ausgedruckt am: 22.11.2024 um 18:11 Uhr

32067
32067 20.01.2012 um 13:49:35 Uhr
Goto Top
Hallo,

schnelle Idee ohne jetzt alles bis ins letzte Durchdacht zu haben face-smile : Hast du beim Hinzufügen der neuen Spalte "Freischaltung" einen Default-Wert angegeben oder stehen da jetzt aktuell eventuell NULLs in dieser Spalte drin?

Dann würde das erste IF immer in den ELSE-Teil laufen weil da eine 0 als Wert bei SQL rauskommt wenn ich das richtig sehe, d.h. Passwort-Prüfung, die dann in die Hose geht.
DanteGabriel
DanteGabriel 20.01.2012 um 14:02:41 Uhr
Goto Top
Guter Einwand, hast Recht Danke, der Auto Wert ist Null, hab d.h. mal das Freischaltung != 0 auf Freischaltung != NULL geändert, aber es verändert sich leider nichts am Problem, habs gerade mal ausprobiert.

mfg: DanteGabriel

edit: Aber ich glaube nicht das es an der NULL liegt, da wie du sagst sonst die erste Abfrage stehts scheitert oder stehts richtig ist. (Das heißt ob man freigeschaltet ist oder nicht spielte keine Rolle) aber so ist es ja nicht. Wenn ich den Nutzer nicht freigeschaltet habe (Testnutzer) kann er sich auch nicht anmelden, schalte ich ihn frei, kann er sich anmelden. (Nur im ersten Fall kommt die falsche Rückmeldung)
nxclass
nxclass 20.01.2012 um 17:50:06 Uhr
Goto Top
Freischaltung != NULL
Freischaltung IS NOT NULL

//Count (also zählen ob vorhanden geht schneller als expliziet den Wert auszulesen und zu prüfen.)
in welcher Dimension ist denn das so ?
dog
dog 20.01.2012 um 19:06:43 Uhr
Goto Top
Unabhängig davon was man falsch im Login eingibt, es erscheint immer nur der String $error_msg = "Der Benutzername oder das Passwort ist falsch.

Stimmt, ist ja auch völlig logisch.
Die $error_msg ist deine else-Bedingung, sie tritt also in jedem Fall ein wo $Fehlercode nicht 1 ist.

Und jetzt liest du dir das mal durch:
http://php.net/manual/de/language.variables.scope.php

Übrigens: COUNT(*) ist nur in genau einem Fall wesentlich schneller als ein normales SELECT: SELECT COUNT(*) FROM table. In allen anderen Fällen liegt die Hauptlast bei der WHERE-Bedingung.
Also spar dir das COUNT, lies die Daten direkt aus und und wirst dieses hässliche if-Konstrukt inkl. zweiter Abfrage auch noch los.
DanteGabriel
DanteGabriel 20.01.2012 um 23:27:29 Uhr
Goto Top
@nxclass:
Achso den != gibt es in SQL nicht? Dachte den würde es auch geben, da es ja =, <>, usw. auch gibt. Aber das erklärt es natürlich Danke face-smile

Zu dem Count, warum das genau schneller geht weiß ich nicht so genau, hatte das beiläufig mal am Rande gelesen. Soweit ich das verstanden habe ist das angeblich deswegen so, weil nicht alle Angaben einzeln geprüft und der Wert ausgegeben werden muss, sondern nur die Anzahl der vorkommenden Datensätze (auf die diese Beschreibung passt) erfasst wird. Inwiefern sich das letztlich wirklich auf die Geschwindigkeit auswirkt kann ich nicht beurteilen soweit reicht mein wissen noch nicht. (Hatte mir das als Randnotiz im Script hinterlegt)

@dog:
Also das mit der error_msg verstehe ich jetzt nicht? Die Error_msg wird immer ausgegeben, wenn entweder die Nutzerdaten nicht mit den Logineingaben übereinstimmen oder aber der User noch nicht freigeschaltet ist, es bleibt aber die selbe Variable die dann jedoch nur einen anderen Wert bzw. String hat.

Zu dem Link, wenn ich das richtig verstehe willst du mir damit sagen, das die Variable nur lokal in der Funktion vorhanden ist, da diese nicht global definiert wurde. Das würde in diesem Fall auch erklären warum der else Zweig genommen wird. Es überrascht mich jedoch, da ich beide sowohl die Funktion (die seperat in einer php liegt) als auch die Logik dynamisch via require reingeladen habe. (Dachte damit würde die globale Definition hinfällig.)

Das die Art der Abfrage nicht besonders elegant ist, hatte ich bereits befürchtet. Da ich mich jedoch erst seit kurzem damit beschäftige ist es mir ein Anliegen, das es erst mal so funktioniert wie ich es mir zuerst überlegt hatte, ist dies der Fall kann ich es immer noch effektiver bzw. schöner gestalten. Außerdem finde ich ist der Lerneffekt dann wesentlich größer.

Ich Danke euch beiden jedenfalls, werde bei nächster Gelegenheit das ganze mal austesten.

mfg: DanteGabriel
nxclass
nxclass 22.01.2012 um 00:08:26 Uhr
Goto Top
Achso den != gibt es in SQL nicht?
natürlich gibt es den - ABER: NULL ist kein Wert - nur ein Zustand, und kann nicht mit != geprüft werden.

siehe dazu; http://dev.mysql.com/doc/refman/5.1/de/comparison-operators.html
DanteGabriel
DanteGabriel 25.01.2012 um 11:11:12 Uhr
Goto Top
Juhu es läuft, Danke für die Hilfe an alle face-smile

Der Fehler lag wie Dog schon richtig sagte darin, das die Ergebnisse der Varriablen nicht global definiert waren.

Die Sache mit dem SQL Null od. 0 verwirrt mich jedoch weiterhin, da beide Werte zum gewünschten Ergebnis führen. Ich habe das eben noch mal expliziet getestet, obwohl als Standartwert in der DB "Null" eingetragen ist, funktioniert die Abfrage sowohl mit IS NOT null, als auch mit != 0.

mfg: DanteGabriel
dog
dog 25.01.2012 um 15:09:34 Uhr
Goto Top
Der Fehler lag wie Dog schon richtig sagte darin, das die Ergebnisse der Varriablen nicht global definiert waren.

Schön, dass du von selbst drauf gekommen bist face-smile

funktioniert die Abfrage sowohl mit IS NOT null, als auch mit != 0.

Stimmt, beides ist ja uch ungleich NULL.
Was aber nicht geht ist != NULL weil NULL kein gültiger Teil einer Vergleichsoperation ist.
mysql> SELECT 1 != NULL;
+-----------+
| 1 != NULL |
+-----------+
|      NULL |
+-----------+


mysql> SELECT 1 IS NOT NULL;
+---------------+
| 1 IS NOT NULL |
+---------------+
|             1 |
+---------------+
DanteGabriel
DanteGabriel 25.01.2012 um 18:23:04 Uhr
Goto Top
Naja alleine drauf gekommen ... ich erinnere mich da an so einen Link... :D

Achso okay, dann hatte mich der Beitrag vorher verwirrt, das Null ein Zustand ist und das gleiche Ergebnis wie die Zahl 0 liefert. Aber so ist es natürlich klar. Danke face-smile

mfg: DanteGabriel