Toast: Mittels javascript eintrag in MSSQL Datenbank

Hallo,
ich such nun schon seit längerem nach einer Lösung für mein Problem, dass ich aus einer Javascript-Funktion heraus einen Datenbankwert aktualisiere.
Dass dies ohne einer Server seitigen Programmiersprache wie PHP nicht möglich ist, ist mir bereits bewusst. Leider bekomme ich die Verbindung zwischen Client (Javascript) und Server (PHP) nicht so ganz hin...

Hier mal die wichtigen teile meines nicht funktionierenden Codes:

index.html:

  
<script type="text/javascript">  
var request_Toggle = new XMLHttpRequest();  
var stock = "og";  
var licht = new Array(21);  
function Licht_Click(lichtnr)  
{  
	var url = "DB_Toggle.php";  
	//Request öffnen  
	request_Toggle.open('post', url , true);  
	//Requestheader senden  
	request_Toggle.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');  
	//Request senden  
	request_Toggle.send('stock=' + stock + '&lichtnr=' + lichtnr);  
	//Request auswerten (PHP hat eig. keinen "Rückgabewert", dient nur zum aufruf der "Request_DB_auslesen" fkt.  
	request_Toggle.onreadystatechange = interpret_Request_Toggle;  
}  
  
function interpret_Request_Toggle()  
{  
	switch (request_DB.readyState)  
	{  
		case 4:  
			if (request_DB.status != 200)  
				alert("AJAX request ist abgeschlossen hat aber folgenden Fehler:" + request.status);  
			else  
			{  
				//Erneutes auslesen und aktualisieren der Werte  
				Request_DB_auslesen(stock);  
			}  
			break;  
		default:  
			break;  
	}  
}  
</script>  

  
<img id="Img_licht8" src="Bilder/licht_0.png" onclick="Licht_Click(8)" style="position:absolute; top:145px; left:970px;" />  

DB_Toggle.php:

  
<?php  
header('Content-Type: text/html; charset=utf-8');  
$stock = $_POST['stock'];  
$lichtnr = $_POST['lichtnr'];  
  
//Mit MSSQL-Server verbinden  
$serverName = "(local)\SQLEXPRESS";  
$connOptions = array("Database"=>"S7_Haus_Variablen");  
$conn = sqlsrv_connect($serverName, $connOptions);  
if($conn === false)  
{  
     echo "Verbindung zu MSSQL-Server fehlgeschlagen.</br>\n";  
     die( print_r( sqlsrv_errors(), true));  
}  
  
switch ($stock)  
{  
	case "og":  
		$query = "UPDATE obergeschoss SET Wert_Toggle=1 WHERE [index]=" + $lichtnr;  
		$stmt = sqlsrv_query($conn, $query);  
		break;  
	case "eg":  
		$query = "UPDATE erdgeschoss SET Wert_Toggle=1 WHERE [index]=" + $lichtnr;  
		$stmt = sqlsrv_query($conn, $query);  
		break;  
	case "ke":  
		$query = "UPDATE keller SET Wert_Toggle=1 WHERE [index]=" + $lichtnr;  
		$stmt = sqlsrv_query($conn, $query);  
		break;  
	case "ga":  
		$query = "UPDATE garage SET Wert_Toggle=1 WHERE [index]=" + $lichtnr;  
		$stmt = sqlsrv_query($conn, $query);  
		break;  
}  
  
sqlsrv_free_stmt($stmt);  
sqlsrv_close($conn);  
  
?>  

Wenn gewünscht kann ich auch gerne die komplette Website hier rein kopieren.

Wichtig ist im Grunde bloß, dass beim einem klick auf ein Bild ein Datenbankwert aktualisiert wird und nach erfolgreicher Aktualisierung eine Javascript Funktion aufgerufen wird, wobei dieser Funktionsaufruf auch nicht unbedingt sein muss.

Die Website wird mittels Passwort geschützt und es greifen, wenn überhaupt, maximal 5 Personen gleichzeitig drauf zu. Ich lege deshalb relativ wenig wert auf Browserkompatibilität und Ressourcenschonung.

Ich hoffe es findet sich jemand der mir bei diesem Problem helfen kann,
Toast

  1. Lieber Toast,

    switch (request_DB.readyState)

    wo kommt die Variable "request_DB" her? Ich sehe sie nirgends definiert. Von Deiner Schreibweise her müsste es eine "globale" Variable sein (nicht gut).

    alert("AJAX request ist abgeschlossen hat aber folgenden Fehler:" + request.status);

    Wo kommt die Variable "request" her? Ich sehe sie nirgends definiert. Von Deiner Schreibweise her müsste es eine "globale" Variable sein (nicht gut).

    $stock = $_POST['stock'];

    $lichtnr = $_POST['lichtnr'];

    Wozu das Umkopieren? Du verschleierst nur, was in "$stock" und "$lichtnr" steht und woher es gekommen ist! Das ist potenziell gefährlich!!  
      
    
    > `$query = "UPDATE obergeschoss SET Wert_Toggle=1 WHERE [index]=" + $lichtnr;`{:.language-php}  
    
    So, hier ist es passiert. Du hast eine Sicherheitslücke für SQL-Injektionen gebaut. Man sieht der Variablen "$lichtnr" nicht an, dass es sich um ungeprüfte POST-Werte handelt. Stünde dort statt der Variablen `$_POST['lichtnr']`{:.language-php}, müssten sofort Deine Alarmglocken schrillen. Lies bitte den [Artikel zur kontextgerechten Kodierung von Daten](http://wiki.selfhtml.org/wiki/Artikel:Kontextwechsel), um solche Unfälle in Zukunft zu vermeiden!  
      
    Liebe Grüße,  
      
    Felix Riesterer.
    
    -- 
    ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
    
    1. Erstmal danke für die zügigen antworten, leider habe in meinem Startpost vergessen zu erwähnen, dass ich von PHP und Javascript, und eigentlich generell von der Webprogrammierung wenig ahnung habe.

      Große teile wurden mithilfe dieses http://ajax.frozenfox.at/ Tutorials erstellt.

      »»»» $stock = $_POST['stock'];
      »»»» $lichtnr = $_POST['lichtnr'];
      »»
      »»Warum das unnötige Umkopieren?
      Welche Methode ist denn besser dazu geeignet um an die variable zu kommen? Ich hab dies, wie einiges anderes auch, aus dem Tutorial übernommen.

      »»Warum wertest du hier kein Funktionsergebnis[*] aus? Interessiert dich nicht, ob bei der Query Fehler auftraten oder nicht? Was sind das überhaupt für Funktionen? sqlsrv_* kennt das PHP-Handbuch nicht.

      Bei den sqlsrv_* funktionen handelt es sich um die Funktionen die man ab php5.3 nehmen muss(?).
      So steht es zumindest hier:
      http://www.php.net/manual/de/mssql.requirements.php

      Wegen der Erkennung von Fehlern, ich wäre im Moment bereits zufrieden wenn der php-Teil überhaupt aufgerufen werden würde, was im Moment glaub ich nicht der Fall ist.

      Nun zu der Sicherheitslücke mit SQL-Injektionen:
      Ich habe vor die Website mittels .htacess komplett zu sichern, ist dann eine Maskierung der Variable immer noch notwendig?
      Ich habe auch nicht vor die Website öffentlich zu machen, sie soll nur für mich und wenige andere Personen zugänglich sein.

      1. Hi!

        $stock = $_POST['stock'];
        $lichtnr = $_POST['lichtnr'];
        Warum das unnötige Umkopieren?
        Welche Methode ist denn besser dazu geeignet um an die variable zu kommen? Ich hab dies, wie einiges anderes auch, aus dem Tutorial übernommen.

        Sie sind bereits da. Das Herankommen funktioniert wie bei jeder anderen Variablen auch: einfach verwenden.

        Wegen der Erkennung von Fehlern, ich wäre im Moment bereits zufrieden wenn der php-Teil überhaupt aufgerufen werden würde, was im Moment glaub ich nicht der Fall ist.

        Glaube versetzt Berge, hilft aber beim Programmieren wenig. Kontrollausgaben anfertigen ist wesentlich effektiver.

        Ich habe vor die Website mittels .htacess komplett zu sichern, ist dann eine Maskierung der Variable immer noch notwendig?

        Immer, ohne Ausnahme. Außerdem muss nicht die Variable maskiert werden sondern der Wert beim Einfügen in das Statement.

        Ich habe auch nicht vor die Website öffentlich zu machen, sie soll nur für mich und wenige andere Personen zugänglich sein.

        Spielt keine Rolle. Ein Angreifer orientiert sich an den Gegebenheiten (zum Beispiel unsichere Passwörter) und nicht an deinen Wünschen.

        Lo!

        1. Sie sind bereits da. Das Herankommen funktioniert wie bei jeder anderen Variablen auch: einfach verwenden.

          Sind sie leider nicht, zumindest haben die Variablen wenn ich diesen Teil weglasse keinen Inhalt.

          1. Hi!

            Sie sind bereits da. Das Herankommen funktioniert wie bei jeder anderen Variablen auch: einfach verwenden.
            Sind sie leider nicht, zumindest haben die Variablen wenn ich diesen Teil weglasse keinen Inhalt.

            Die Werte, die dich interessieren sind im Array $_POST. Man muss sie nicht von dort rauskopieren, man kann ganz einfach das jeweilige Element des $_POST-Arrays verwenden.

            Also statt

            $stock = $_POST['stock'];
              switch ($stock)

            kann und sollte man besser gleich

            switch ($_POST['stock'])

            schreiben.

            Lo!

    2. Entschuldigung für den Doppelpost, ich bin mit der Forensoftware leider noch nicht so ganz vertraut und fand keinen Edit-Button.

      switch (request_DB.readyState)
      wo kommt die Variable "request_DB" her? Ich sehe sie nirgends definiert. Von Deiner Schreibweise her müsste es eine "globale" Variable sein (nicht gut).

      statt request_DB sollte hier request_Toggle stehen, hab vergessen das umzuändern.

      alert("AJAX request ist abgeschlossen hat aber folgenden Fehler:" + request.status);
      Wo kommt die Variable "request" her? Ich sehe sie nirgends definiert. Von Deiner Schreibweise her müsste es eine "globale" Variable sein (nicht gut).

      Es handelt sich bei den Variablen um globale Variablen:

        
      var request_Toggle = new XMLHttpRequest();
      

      Haben die globalen Variablen in diesen fall denn einen nachteil?
      Immerhin benötige ich die Variable in mehreren Funktionen und ich dachte mir das eine Globale Variable hier die Effektivste Lösung wäre.
      Welchen Weg würdest du mir stattdessen vorschlagen?

      1. Lieber Toast,

        Es handelt sich bei den Variablen um globale Variablen:
        var request_Toggle = new XMLHttpRequest();

        nicht gut, wie schon erwähnt.

        Haben die globalen Variablen in diesen fall denn einen nachteil?

        Ja, denn Deine Funktionen können sie nach Belieben überschreiben.

        Du verwendest asynchrone HTTP-Requests, die vielleicht im Rudel auftreten. Wenn Du mehrere Requests nacheinander abschickst, sie sozusagen in einer Warteschlange stehen, alle dieselben globalen Variablen benutzen, dann rate doch einmal was passiert...!?

        Nicht umsonst erzeugst Du ein _neues_ XMLHttpRequest-Objekt, da das alte bereits benutzt wird. Damit hast Du ein neues Objekt, dessen Eigenschaften Du neu beschreiben/auslesen/verwerten kannst. Globale Variablen hindern Dich da nur.

        Welchen Weg würdest du mir stattdessen vorschlagen?

        Stelle Dir die XHR als Menschen vor, die mit einer Tasche in der Hand an der Supermarktskasse stehen. Jeder XHR wurde neu erzeugt, hat seine _eigene_ Tasche und will seine speziellen _eigenen_ Kaufwünsche an der Kasse einlösen. Das bedeutet, dass Du objektorientiert schreiben musst. Deine funktionale Sichtweise hat Dich in die Sackgasse der globalen Variablen geführt. Was Du stattdessen brauchst, ist das Arbeiten mit asynchronen Methodenaufrufen. Ob das Timeout-gesteuerte Aufrufe sind, oder ob sie von einem XHR-Objekt her stammen, ist egal. Du musst eben Deine Funktionen so schreiben, dass sie Objekte entgegennehmen und relativ losgelöst vom restlichen Programmverlauf ihren Dienst tun.

        Liebe Grüße,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
  2. Hi!

    Leider bekomme ich die Verbindung zwischen Client (Javascript) und Server (PHP) nicht so ganz hin...
    Hier mal die wichtigen teile meines nicht funktionierenden Codes:

    Nun, wenn es dein Code ist, dann weißt du ja, wie er arbeiten soll. An welcher Stelle genau weicht denn die Wirklichkeit von deiner Vorstellung ab?

    $stock = $_POST['stock'];
    $lichtnr = $_POST['lichtnr'];

    Warum das unnötige Umkopieren?

      $query = "UPDATE obergeschoss SET Wert\_Toggle=1 WHERE [index]=" + $lichtnr;  
      $query = "UPDATE erdgeschoss SET Wert\_Toggle=1 WHERE [index]=" + $lichtnr;  
      $query = "UPDATE keller SET Wert\_Toggle=1 WHERE [index]=" + $lichtnr;  
    

    Wo ist die notwendige Maskierung oder ein Zwangs-Typecast nach Zahl, um unter anderem SQL-Injection zu verhindern?

      $query = "UPDATE garage SET Wert\_Toggle=1 WHERE [index]=" + $lichtnr;  
      $stmt = sqlsrv\_query($conn, $query);  
      break;  
    

    Warum wertest du hier kein Funktionsergebnis[*] aus? Interessiert dich nicht, ob bei der Query Fehler auftraten oder nicht? Was sind das überhaupt für Funktionen? sqlsrv_* kennt das PHP-Handbuch nicht.

    [*] angenommen, es gibt eins, das wie beim Connect den Erfolgsstatus mitteilt

    Lo!

  3. Hallo,

    Hier mal die wichtigen teile meines nicht funktionierenden Codes:

    definiere "funkioniert nicht".

    $query = "UPDATE obergeschoss SET Wert_Toggle=1 WHERE [index]=" + $lichtnr;

    Dir ist bewusst, dass das '+' an der Stelle nicht das bewirkt was es in Javascript bewirken würde?

    Gruß,
    Tobias

    1. Hallo,

      Hier mal die wichtigen teile meines nicht funktionierenden Codes:

      definiere "funkioniert nicht".

      $query = "UPDATE obergeschoss SET Wert_Toggle=1 WHERE [index]=" + $lichtnr;

      Dir ist bewusst, dass das '+' an der Stelle nicht das bewirkt was es in Javascript bewirken würde?

      Gruß,
      Tobias

      Nein war es nicht.
      Hab das + nun durch einen .  ersetzt und die Website mach nun genau das was sie auch machen soll :)

      Herzlichen dank für deine Antwort.

      1. Hi!

        $query = "UPDATE obergeschoss SET Wert_Toggle=1 WHERE [index]=" + $lichtnr;
        Dir ist bewusst, dass das '+' an der Stelle nicht das bewirkt was es in Javascript bewirken würde?
        Nein war es nicht.

        Dass hier was nicht arbeitet wie gewünscht, hätte man auch mit einer Kontrollausgabe sehen können. Das Statement sieht dann nämlich anders als geplant aus.

        Lo!