# Formular an Webserver (node.js) senden und in DB speichern



## ByeBye 273232 (9. Dezember 2013)

Guten Tag,

ich mache gerade eine App mit jQuery mobile und PhoneGap (Android). Ich möchte in Login System bauen. Dafür muss ich die Daten des Login bzw. Registrierungsformular an eine Datenbank eines Webservers senden (und sie per PhoneGap im localstorage speichern, aber das ist ne andere Geschichte).

Die Formulare sind fertig, ein simpler Webserver (Linux Ubuntu) mit node.js eingerichtet. Könnte auch auf PHP ausweichen, falls es für node kein Tutorial oder Hilfe gibt, aber node.js wäre mir lieber.

Nun muss ich im nächsten Schritt die Daten des Formulars (E-Mail, Passwort etc.) an den Server senden. Dort muss dann der Server die Daten empfangen und in eine Datenbank (MySQL?) speichern.

Beim senden der Daten und speichern in die DB hab ich Probleme. Finde kein geeignetes Tutorial. Kann mir da jemand helfen oder vielleicht ein Tutorial empfehlen? Ich weiß, dass man da viel falsch machen kann wegen Sicherheit etc.


----------



## Joe (9. Dezember 2013)

Das was du suchst ist Ajax -Post oder Jquery.Ajax -Post:
http://www.w3schools.com/ajax/
http://api.jquery.com/jQuery.post/

Kleines Beispiel:

```
function send() {
	var var1="Text";
	var Name="Max Muster";
	jQuery.ajax({
		url: 'includes/update.php',
		type: 'POST',
		data: {Variable1: var1, Variable2: Name},
		success: function(data){
			window.location.href = data;
        },
		error: function() {
			alert('Ein Fehler ist aufgetreten');
		}
	});
}
```


----------



## ByeBye 273232 (9. Dezember 2013)

Hallo Joe und danke, das ist mal ein Anfang. Das Update.php kann ich ja durch ein js Script ersetzen.

Kann ich so auch einfach ein Passwort übertragen oder ist das zu unsicher?


----------



## Joe (9. Dezember 2013)

Also das Passwort solltest du vorher verschlüsseln und salzen!
Javascript wird clientseitig ausgeführt um die Daten auf den Server zu verarbeiten speichern oder abrufen braucht es eine serverseitige Sprache wie zb. PHP und eine Datenbank wie zb. MySQL.

Mal Nen Beispiel einer update.php auf deinen Server:

```
<?php
header('Content-Type: text/html; charset=iso-8859-1');
$link = mysql_pconnect("localhost", "User", "PW");
		mysql_select_db("Datenbankname", $link);

$Variable1 = trim($_POST['Variable1']);
$Variable1 = mysql_real_escape_string($Variable1);
$Variable1 = utf8_decode($Variable1);
$Variable2 = trim($_POST['Variable2']);
$Variable2 = mysql_real_escape_string($Variable2);
$Variable2 = utf8_decode($Variable2);

mysql_query("INSERT INTO
				User
					(Username,
					Passwort)
				VALUES
					('$Variable1',
					'$Variable2')");


echo "Erledigt!";
?>
```

Zum Thema Sicherheit: traue niemals einer Eingabe ob nun Post Get Cookie oder egal alles immer prüfen und mit mysql_real_escape_string() entschärfen. Das Passwort sollte sofort nach Eingabe noch vor dem Senden verschlüsselt werden da Javascript keine eigne md5() Funktion hat musst wohl mal schauen es gibt Scripte die genau das machen.

Ich hoffe das hilft etwas weiter.


----------



## ComFreek (9. Dezember 2013)

Joe, tut mir leid, wenn ich das jetzt so sage, aber in deinem Beitrag sind echt viele Dinge, die man *überhaupt niemals* tun sollte!

1. Die alte MySQL-Erweiterung auf keinen Fall mehr nutzen! Auf MySQLi oder PDO ausweichen. Bei MySQLi unbedingt auch Prepared Statements nutzen.
Bei Prepared Statements braucht man auch keine Escape-Funktion mehr!
Außerdem würde ich nicht zu persistenten Verbindungen von vornherein raten (das 'p' in mysql_pconnect() bzw. 'p:' beim Host-Parameter für [phpf]mysqli_connect()[/phpf]).

2. Wozu [phpf]utf8_decode[/phpf]? Lies dir mal bitte die Dokumentationsseite dazu durch. Nicht einfach so nach Lust und Laune anwenden!

3.  Wieso den Charset im header()-Befehl nicht gleich auf UTF-8 setzen?

4. Auf keinen Fall mehr MD5 benutzen!!
5. Auch verschlüsselt MD5 nicht! Es ist ein Hash-Algorithmus. Wenn schon ist es eine Einwegverschlüsselung.

==> bcrypt zum Hashen auf dem Server verwenden!

6. Wozu das Passwort auf der Clientseite hashen? Da wird der Hash auch nur zum eigentlichen Passwort umfunktioniert --> kein Sicherheitsgewinn*

==> HTTPS zur Übertragung nutzen

7. [phpf]trim[/phpf] beim Nutzernamen verstehe ich es noch, aber beim Passwort? Wieso willst du bestimmte Whitespaces (siehe trim-Doku) beim Passwort am Anfang und am Ende ausschließen?

*) Man könnte natürlich argumentieren, sofern man kein HTTPS nutzt, dass wenn ein Angreifer das Passwort im Klartext abgreift, dass er möglicherweise auch bei anderen Nutzeraccounts deines Nutzes Zugriff erlangen könnte, sofern der Nutzer das gleiche Passwort mehrfach verwendet. Doch wenn man HTTPS nutzt, dann ist diese Tatsache sowieso egal.


----------



## ByeBye 273232 (10. Dezember 2013)

Hi ComFreek

genau das ist mein Problem. Man liest etwas im Internet und der nächste sagt, das sei unsicher und dürfe man so nicht verwenden. Daher suche ich ein gutes Tutorial oder eine Anleitung, um einfach folgendes sicher auszuführen mit JavaScript:

- Userdaten an den Server senden und in einer Datenbank abspeichern

Habe  bisher leider keine gute Anleitung gefunden, kennst du evtl. eine?


----------



## Joe (10. Dezember 2013)

> Joe, tut mir leid, wenn ich das jetzt so sage, aber in deinem Beitrag sind echt viele Dinge, die man überhaupt niemals tun sollte!


Kein Problem ich lerne gern dazu.

Zu 1.ens: Das empfinde ich schon als Tortur zb auf meiner Seite den gesamten Code durch zuarbeiten und auf MySQLi umzucoden.
Welche eklatante Lücke ist denn da bekannt geworden das man nun öfters davon hört man solle kein MYSQL mehr nutzen?

Zu 2.ens und 3.ens: Ganz ehrlich das habe ich bis heute noch nicht kapiert. Notepad++ stellt mir entweder komische Zeichen dar oder ich habe keine Umlaute auf der Seite. Also habe ich kurzerhand alles auf iso-8859-1 gestellt. Jedoch kommt durch Ajax wieder UTF8 an also decodiere ich es wieder zu iso-8859-1. Ich gebe zu das ich das einfach nie verstanden habe und es aber wenigstens die Umlaute korrekt darstellt.

Zu 4.ens: ? Seit wann ist md5 verpönt? Hm gut kurze oder bekannte Wörter wurden glaube ich bereits entschlüsselt aber nen 8stelliges Passwort über md5 gehasht ist anfällig? Dann sollte man die Funktion auch als depracated bezeichnen stattdessen wird dies überall als Standard angepriesen. Da gibt es Unmengen an Tutorials zu Logins und Registrierung woher soll der Leihe denn wissen das dies plötzlich eine Sicherheitslücke darstellt?
Da wäre ein Tutorial hier auf Tutorials.de wirklich nicht schlecht.

Zu 7.ens: ist bei mir fälschlicherweise ohne zu überlegen als Sicherheitsmaßnahme hängen geblieben.

Ja was soll ich sagen du hast absolut Recht ich habe da einigen Stuss drinnen und sogar leichte Lücken. An mysql_real_escape_string vorbei zu kommen das möchte ich erstmal sehen.
Verstehe mich nicht falsch ich glaube dir schon was du sagst, nur bin ich so wenn ich eine Lücke verstehe wie sie zustande kommt wird mir das ganze Ausmaß meist besser bewusst und ich versuche es zu ändern.

Ganz falsch ist aber das Grundprinzip des Beispiels oben nicht. Wie würde der BeispielCode idealerweise nun aussehen.. damit es Struct weiterhilft?
Ich mein Sicherheit hin oder her um AJAX wird er nicht drum rum kommen. Es sei denn es gibt hier noch etwas was ich nur noch nicht kenne  (was durchaus möglich ist).

Aber trotzdem Danke für das Aufzeigen meiner Fehler.

Gruß Joe.


----------



## sheel (10. Dezember 2013)

@Joe:

1: Warum die PHP-Mysql-Extension "schlecht" ist:
Es ist nicht so, dass plötzlich eine riesige Sicherheitslücke bekannt wurde,
die keiner beheben kann. Aber: Der "Support" (Funktions-/Sicherheitsupdates)
für die Software wird bzw. ist schon eingestellt.
Zurzeit ist die Sache noch aktiv, aber das Ende ist geplant.
3 Auswirkungen:

a) Sicherheitsprobleme, die evt. irgendwann gefunden werden,
werden dann wirklich nicht mehr behoben, einfach, weil keiner seine Zeit mehr für das opfert.

b) Eventuell sind schon heute Sich.probleme bekannt, die absichtlich bis zum Supportende
geheim gehalten werden, und dann im großen Stil ein Angriff auf alte
noch-AltMysql-verwendenden Server erfolgt.

c) Unabhängig von der Sicherheit gibts keine Garantie, wie lang die Software überhaupt
noch funktioniert. Bei PHP und der Datenbank Mysql selbst gibt es immer wieder neue Versionen,
die neue und geänderte Funktionen haben (und manchmal auch alte Funktionen nicht mehr
vorhanden sind). Irgendwann wird es soweit sein, dass die ewig nicht mehr angepasste
Mysql-Extension mit den neuen Versionen der Hauptsoftware einfach nicht mehr
zusammen funktioniert.

Man könnte die Sache selst in die Hand nehmen, die Extension programmiermäßig immer
anzupassen, aber hat man die Zeit und das Knowhow dazu?
...



2/3: Irgendwo wird wohl ein Teil deiner Seite (HTML-Dateien, PHP-Code, DB-Tabellen usw.usw.)
nicht mit UFT8 arbeiten. was du versuchst ist, alles andere entsprechend anzupassen.
Warum nicht die eine Problemstelle suchen? (oder auch mehrere)
Wenn alles einheitlich UTF8 (oder alles ISO8850-1 oder...) ist
gibts garantiert keine Probleme mehr.
Und warum man mehr Richtung UTF statt Einbytecharsets geht
ist eben, damit das Chaos mit den hunderten Einbyte-Systemen ein Ende hat
(einfacher für den Programmierer )
und jeder, egal woher, deine Seiten auch richtig sieht.



4: MD5 wurde 1991 erfunden, und seit 1996 gibt es Leute, die daran
Sicherheitsprobleme wissen (mehr oder weniger schwerwiegend).

Was MD5 ja sein sollte: Zu einem Hash kann man den Ausgangstext nicht bestimmen
(bzw. nur in Zeiträumen wie 1000 Jahren oder so, also zu lang für Menschenleben)
Was MD5 heute (2013) ist: Bestimmte Attacken werden in einer einzelnen Sekunde  durchgeführt. Gute Computer vorausgesetzt, aber möglich.
Und auch ohne Forschungsförderungen etc. kann man das Zeug
in einer erträglichen Zeit brechen.

SHA1 war eine Zeit lang die Empfehlung als MD5-Ersatz,
aber auch SHA1 ist nicht mehr das Wahre...

Und gerade im PHP-Bereich gibt es leider sehr viele alte Tutorials überall im Internet,
die bei Datenbanksoftware und Hashalgorithmen leider völlig veraltete Sachen beibringen
(was zum Erstellungszeitpunkt vllt. noch gut war, heute aber nicht mehr)
Sicher ist das für Anfänger gar nicht gut, die das damit falsch einlernen,
aber viel ändern kann man leider nicht an der Situation.


----------



## ComFreek (10. Dezember 2013)

Neuer Beispielcode
Anmerkungen:

Die DB-Verbindungherstellung und die Abfrage sollten idealerweise in einer DB-Klasse geschehen


```
<?php

if (!isset($_POST['username']) || !isset($_POST['password'])) {
  // Parameter wurden nicht übertragen --> Fehler!
  http_response_code(403);
  exit('Access denied');
}

$user = $_POST['username'];
$password = $_POST['password'];

try {
  $db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password', array(
    PDO::ATTR_EMULATE_PREPARES => false,
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
  ));

  $stmt = $db->prepare("SELECT pw FROM table WHERE user=? LIMIT 1");
  $stmt->execute(array($user, $password));
  $pwRow = $stmt->fetch(PDO::FETCH_NUM);
}
catch(PDOException $e) {
  // Fehler bei der Abfrage aufgetreten
  // Sollte normalerweise nicht passieren!
  // Natürlich den Fehler protokollieren (Log)!
  http_response_code(500);
  exit('Internal server error. Contact the web master');
}

if (password_verify($password, $pwRow[0])) {
  // TODO password correct
}
else {
  // TODO password incorrect
}
```

Daumen hoch, dass du nach den Gründen fragst!

Zu 1.:
Dass bestehenden Code umzuschreiben mühselig ist, kann ich verstehen. Hier würde sich zum Beispiel eine Datenbank-Klasse anbieten, die die gebräuchlichsten Funktionen des jeweiligen Datenbank-Treibers (hier MySQL(i)) enkapsuliert und deren Funktionalität über allgemein-benannte Funktionen bereitstellt (z.B. "$db->query()" statt "$db->mysqli_query()"!). Somit müsstest du im besten Fall nur die DB-Klasse intern umschreiben, falls du wieder einmal den Datenbanktreiber wechselst, Log-Funktionalitäten einbauen möchtest oder einfach Unit Tests schreibst.


Zu 2. und 3.:
Wie gesagt, schau dir mal bitte die Doku von [phpf]utf8_encode[/phpf] und [phpf]utf8_decode[/phpf] an:


			
				utf8_encode hat gesagt.:
			
		

> data
> An ISO-8859-1 string.





			
				utf8_decode hat gesagt.:
			
		

> This function decodes data, assumed to be UTF-8 encoded, to ISO-8859-1.


Die Namen sind leider schrecklich gewählt! Man kann das Encoding eines Strings nie in ein anderes umwandeln, wenn man das vorherige nicht kennt. Hier wird "ISO-8859-1" als aktuelles bzw. vorheriges Encoding angenommen!

Am besten einfach alles in UTF-8 speichern!
Wenn du Hintergrundinfos willst (was ich absolut empfehlen würde!), dann kann ich diesen Artikel nur wärmstens empfehlen:
http://kunststube.net/encoding/

Zu 4.:
Schon lange sollte man MD5 nimmer nutzen. Eine genaue Jahreszahl kann ich dir jetzt aus dem FF aber auch nicht nennen.



			
				Joe hat gesagt.:
			
		

> gut kurze oder bekannte Wörter wurden glaube ich bereits entschlüsselt


"Entschlüsseln" ist hier der falsche Ausdruck. Es gibt den Begriff von "Rainbow Tables". Das sind schlichtweg Tabellen, in denen Zeichenkombinationen und ihr MD5-Pendant abgespeichert sind.

Das Problem an MD5 ist vor allem, dass es zu schnell berechenbar ist!! Man kann sehr leicht mehrere Millionen Hashes in kürzester Zeit berechnen.



			
				Joe hat gesagt.:
			
		

> Dann sollte man die Funktion auch als depracated bezeichnen


Im PHP-Manual befindet sich bereits ein Hinweis:


			
				php.net hat gesagt.:
			
		

> Note: Secure password hashing
> It is not recommended to use this function to secure passwords, due to the fast nature of this hashing algorithm. See here for details.



Außerdem kann man MD5-Hashes auch zur Verifikation von Datenintegrität nutzen. Bei Downloadangeboten (meist von Opensource-Projekten) werden oft MD5-Hashes für die Dateien bereitgestellt. Hat man nun eine Datei runtergeladen, kann man ihren MD5-Hash berechnen lassen und so verifizieren, dass die Datei Bit für Bit korrekt runtergeladen wurde.
Dass zwei verschiedene Datenströme den gleichen MD5-Hash ergeben lassen, ist zwar theoretisch und praktisch möglich, jedoch ist die Wahrscheinlichkeit bei einem "normalen" Download extrem gering.

Du hast Recht, Laien können zwischen vorbildlichen Beispielen und schlechten Beispielen natürlich nicht differenzieren. Das kann keiner, der sich ein neues Fachgebiet aneignet.
Zu Sicherheitsthemen kann ich http://security.stackexchange.com empfehlen. Fast alle hochbewerteten Antworten da sind vertrauenswürdig.



			
				Joe hat gesagt.:
			
		

> An mysql_real_escape_string vorbei zu kommen das möchte ich erstmal sehen.


Siehe hier: http://stackoverflow.com/a/12118602/603003
Außerdem, wenn man die Funktion mysql(i)_real_escape_string missbraucht: http://stackoverflow.com/a/5741264/603003


----------



## Joe (10. Dezember 2013)

@Sheel und ComFreek

Zu 1.ens: Ok glasklar es wird eingestellt und somit kommt man irgendwann nicht drum rum alles ab zu ändern.
Gut dann ist es richtig das man jedem gleich diese Tatsache bewusst macht. Ich hoffe nur ich muss nicht komplexe Joins nun zerlegen (für komplex Yaslaw löst sowas ja in Sekunden-Minuten  ).

Zu 1ens: Gibt es ein MySQLi Äquivalent als persistente Verbindung also mysql_pconnect() ? Da ich zb ne Liveanzeige der PNs oder Useronline habe werden bei mir pro User ne Menge Ajax Requests gefeuert und auch so habe ich teils nicht gerade sparsame SQL Anfragen so das ich auf ein maximales Verbindungslimit von 25k pro Stunde schon bei 10 Usern kommen kann.


Zu 2ens: Ich denke das Problem ist irgendwann bei mir eingeschlichen nach einen DB-Backup welches in falschen Format exportiert wurde oder falsch importiert. Und irgendwie habe ich es dann nie richtig verstanden wie man hier nun was richtig oder falsch macht. Werde mir das alles nochmal in Ruhe anschauen denn auf Dauer immer wieder mit den Konvertierungen zu kämpfen ob nun Editor, DB oder serverseitig bis sogar clientseitig (Ajax) nervt extrem.
Werde mir den Link von ComFreak anschauen.

Zu 4ens: Vielen Dank für euren Ausführungen. 





> Und auch ohne Forschungsförderungen etc. kann man das Zeug
> in einer erträglichen Zeit brechen.


  hier musste ich kurz lachen.. ist ja ne aktuelle Debatte.


> ==> bcrypt zum Hashen auf dem Server verwenden!


Nun aber wie nachträglich die bereits angemeldeten PWs hashen? Lässt man die User die PWs ändern? Die User werden denken "Oha die wurden wohl gehackt". Hm obs da ein Workaround gibt?

Jedenfalls danke ich euch beiden ich schaue mir das alles nochmal genau an.


.


----------



## ComFreek (10. Dezember 2013)

Joe hat gesagt.:


> Zu 1ens: Gibt es ein MySQLi Äquivalent als persistente Verbindung also mysql_pconnect() ?




```
<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(
  PDO::ATTR_PERSISTENT => true
));
?>
```

Siehe auch hier.



Joe hat gesagt.:


> Nun aber wie nachträglich die bereits angemeldeten PWs hashen?


Ganz einfach: beim nächsten Login wird ja das Passwort in Klartext an das PHP-Skript übergeben. Sofern es richtig eingegeben wurde (alte Hashes stimmen überein), bietet sich die Möglichkeit den neuen Hash berechnen zu lassen. 

Wegen den Encoding-Problemen kannst du dir auch mal diese Frage und ihre Antworten anschauen: http://stackoverflow.com/questions/279170/utf-8-all-the-way-through


----------



## ByeBye 273232 (14. Dezember 2013)

Guten Abend

Erstmal Danke für die interessanten Beiträge. Ich hätte hierzu noch ein paar Fragen:

1. Ich wollte ja eigentlich node.js verwenden. Wenn ich nun aber das Skript von ComFreek aus Beitrag 9 nutze muss ich ja auf meinen Linux Server Apache und MySQL installieren. Das müsste ja trotzdem klappen gell? Dann brauch ich nur noch ein JavaScript für mein jQuery Mobile, das die Daten an den Server an das PHP Skript von ComFreek sendet, korrekt?

2. Kann ich von einer externen PostgreSQL Datenbank irgendwie Daten auslesen (Login Daten habe ich) und dann auf meinem Webserver in der MySQL Datenbank speichern? Ich google und google aber finde nichts passendes. 

Schönen Abend,
Sebastian


----------



## Joe (15. Dezember 2013)

Ja du benötigst Apache und eine Datenbank. Du kannst auch PostgreSQL installieren oder MySQL.
Zum senden der Daten kommst du nicht um AJAX herum! ( siehe meinen ersten Post).
Das PHP-Script von Comfreak verarbeitet dann die ankommenden Daten auf deinem Server.
Die AJAX-Funktionen success und error geben dir die Möglichkeit sogar Daten weiter zu verarbeiten.

Der Zugriff auf die externe? PostgreSQL Datenbank geschieht hier auch wieder mit PHP. Die Daten speicherst du in Variablen und kannst sie dann an MySQL schicken.


----------



## ComFreek (16. Dezember 2013)

1. Für NodeJS sollte es sicherlich auch eine PostreSQL-Bibliothek geben. Gerade eine gefunden: https://github.com/brianc/node-postgres

2. Sollte klappen. Für den Host dann einfach statt "localhost" die externe IP (oder Domainnamen) angeben.

Wenn du PHP nimmst, kann ich Joe nur zustimmen!


----------

