Eine eigene PHP-Web-API bauen

Um Daten aus dem SmartHome auf eine eigene Website zu bringen, habe ich mir eine Authentifizierung gebaut, die es mir erlaubt, per POST Request Daten bereitzustellen – und zwar nur mir. Einfach nur ein festes Passwort war mir da zu unsicher. Daher habe ich eine zeitbasierte Komponente mit eingebaut.

Zum Einsatz kommt seitens Node-RED node-red-contrib-cryptography.

Ich generiere einen Auth Token, dieser basiert auf der aktuellen Zeit und einem geheimzuhaltenden Passwort, quasi einem Salt.

msg.payload = Math.round(Date.now()/10000) + "dasGeheimePasswort1234!";
msg.headers = {};
msg.headers["Content-Type"] = "application/x-www-form-urlencoded";
return msg;

Beim Token habe ich mich für eine Gültigkeit von 10 Sekunden (daher geteilt durch 10.000) entschieden, dann sind minimale Ungenauigkeiten bei den Uhrzeiten zwischen SmartHome und Webserver nicht so dramatisch. Der Payload wird dann durch die hash-Funktion sha256 gehasht. Anschließend wird der POST Request mit Daten bepackt und der http request abgeschickt.

msg.payload = {
"auth": msg.payload,
"temperatur": msg.temperatur
};
return msg;

Um dem POST Request zu empfangen und zu authentifizieren muss die PHP Gegenstelle den gleichen Token generieren und mit dem mitgeschickten Token abgleichen. Dazu braucht die Gegenstelle natürlich auch den auf 10 Sekunden gerundeten Timestamp und das gleiche geheime Passwort, wie es im Node-RED hinterlegt ist.

<?php
   if($_POST["auth"] == hash('sha256',(round(time()/10))."dasGeheimePasswort1234!")) {
echo "true";
}
?>

Achtung! PHP arbeitet bei den Timestamps in Sekunden, während JavaScript in Millisekunden arbeitet. Daher ist hier nur eine Division durch 10 nötig.

Statt dem echo „true“; kann man natürlich beliebiges mit den mitgeschickten Werten anfangen.

POST-HTTP Request mit Daten

Da ich mich sehr dumm angestellt habe und ewig brauchte, um mit Node-RED einen HTTP Request inkl. Daten zu versenden, dokumentiere ich hier – nur für mich (weil sich bestimmt niemand so umständlich anstellt) – die funktionierende Lösung.

Der simple Aufbau, ein Function-Node und ein HTTP-Request-Node:

Im Function-Node werden die zu übermittelnden Daten in msg.payload als JSON geschrieben. Außerdem wird
msg.headers["Content-Type"] = "application/x-www-form-urlencoded";
gesetzt.

Der HTTP-Request ist dann kaum zu konfigurieren. Methode = POST eintragen, dann noch die URL und fertig.