Eine HTTP GET-Request ist ein fundamentales Konzept der Webkommunikation. Sie ermöglicht es einem Gerät, wie zum Beispiel dem ESP8266, Informationen von einem Webserver abzurufen. Ein typisches Beispiel hierfür ist das Anfordern von Daten über eine URL, ähnlich dem Klicken eines Links in deinem Webbrowser.
Stell dir vor, du hast eine URL wie httpbin.org/ip. Wenn diese URL aufgerufen wird, führt der Server seinen Code aus und sendet eine Antwort an den Client zurück. Die Antwort kann in einem einfachen Webbrowser wie folgt aussehen:
Produktempfehlungen und -suche in Verbindung mit dem Amazon Partnerprogramm:
¹ Angaben ohne Gewähr. Bei einem Kauf über den Link erhalten wir eine Provision.
{
"origin": "109.43.51.52"
}
Solch eine Serverantwort kann via GET-Request und ESP8266 gelesen werden. Darauf basierend kann der ESP die Daten dann anzeigen, verwerten oder andere Aktionen ausführen. Der ESP8266 kann mithilfe einer GET-Request zum Beispiel als Fernbedienung für einen anderen ESP dienen. Siehe dazu: ESP8266 WLAN-Relais mit HTTP API.
Zum Kapitel springen Programmcode
Zum Kapitel springen Informationen
In den folgenden Beispielcodes demonstriere ich, wie man mit einem ESP8266 sowohl HTTP- als auch HTTPS-GET-Requests durchführt. Der Unterschied zwischen HTTP und HTTPS liegt in der Sicherheit der Datenübertragung, wobei HTTPS eine verschlüsselte Verbindung bietet.
Unabhängig davon, ob die GET-Anfrage an ein Backend wie Node.js gesendet wird, ein anderer ESP8266 als Webserver fungiert oder eine andere Technologie zum Einsatz kommt: Der Prozess der Datenanforderung und -übermittlung bleibt gleich.
Für die beiden Beispielcodes müssen Anpassungen vorgenommen werden. Diese beschränken sich zum einen auf die Zugangsdaten zu eurem WLAN-Netzwerk, zum anderen natürlich auf die URL die abgerufen werden soll.
// WLAN-Zugangsdaten anpassen
const char* ssid = "WLAN_SSID";
const char* password = "WLAN_PASSWD";
// URL der Anfrage anpassen
sender.begin(wifiClient, "http://httpbin.org/ip");
Zum Kapitel springen Anfrage an HTTP
Der folgende Code unterstützt nur die Request an einen HTTP-Server. Solltest du einen Server abrufen wollen, der HTTPS verwendet, nutze dieses Snippet.
/*
HTTP-GET Request
Basic-Code für GET-Request an einen HTTP-Server
Created by cooper.bin, 2020
makesmart.net
*/
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
HTTPClient sender;
WiFiClient wifiClient;
// WLAN-Daten
const char* ssid = "WLAN_SSID";
const char* password = "WLAN_PASSWD";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(200);
Serial.print(".");
}
Serial.println("Verbunden!");
if (sender.begin(wifiClient, "http://httpbin.org/ip")) {
// Optional; Falls Header für Authentifizierung o.ä gesetzt werden sollen
// sender.addHeader("Authorization", "Bearer dein_token_hier");
// HTTP-Code der Response speichern
int httpCode = sender.GET();
if (httpCode > 0) {
// Anfrage wurde gesendet und Server hat geantwortet
// Info: Der HTTP-Code für 'OK' ist 200
if (httpCode == HTTP_CODE_OK) {
// Hier wurden die Daten vom Server empfangen
// String vom Webseiteninhalt speichern
String payload = sender.getString();
// Hier kann mit dem Wert weitergearbeitet werden
// ist aber nicht unbedingt notwendig
Serial.println(payload);
}
}else{
// Falls HTTP-Error
Serial.printf("HTTP-Error: ", sender.errorToString(httpCode).c_str());
}
// Wenn alles abgeschlossen ist, wird die Verbindung wieder beendet
sender.end();
}else {
Serial.printf("HTTP-Verbindung konnte nicht hergestellt werden!");
}
}
void loop() {
}
Zum Kapitel springen Anfrage an HTTPS
Dieser Beispielcode ist ziemlich identisch zu dem für HTTP-Anfragen. Da wir hier mit einer verschlüsselten Verbindung arbeiten müssen zwei Anpassungen vorgenommen werden. Beide betreffen den HTTP-Client.
WiFiClient wifiClient;
// wurde zu
WiFiClientSecure wifiClient;
Zusätzlich, da wir hier erstmal ohne Fingerprint arbeiten, müssen wir den HTTP-Client vor der eigentlichen Anfrage auf insecure setzen.
wifiClient.setInsecure();
Der Befehl wifiClient.setInsecure();
ist eine wichtige Zeile, wenn es um die Nutzung von HTTPS-Verbindungen mit dem ESP8266 geht. Diese Zeile bewirkt, dass der ESP8266 keine Überprüfung des SSL/TLS-Zertifikats des Servers durchführt. Das ist erstmal kein Problen, jedoch sollte man dabei ein paar Dinge Dinge beachten:
- Durch das Deaktivieren der Zertifikatsüberprüfung mit
setInsecure()
akzeptiert der ESP8266 alle SSL/TLS-Zertifikate des Servers, unabhängig davon, ob sie gültig oder von einer vertrauenswürdigen Zertifizierungsstelle ausgestellt sind. Dies könnte Man-in-the-Middle-Angriffe ermöglichen, bei denen ein Angreifer möglicherweise gefälschte Zertifikate verwenden könnte, um sich als der legitime Server auszugeben. - Die Einstellung kann in bestimmten Szenarien nützlich sein, insbesondere in Testumgebungen oder wenn eine Verbindung zu Servern hergestellt wird, deren Sicherheit bekannt und vertrauenswürdig ist.
- Sollten sensible Informationen ausgetauscht werden, sollte diese Option eher nicht verwendet werden. Mehr dazu im Kapitel Hinweise zu HTTPS Anfragen mit Zertifikat.
/*
HTTPS-GET Request
Basic-Code für GET-Request an einen HTTPS-Server
Created by cooper.bin, 2020
makesmart.net
*/
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
HTTPClient sender;
WiFiClientSecure wifiClient;
// WLAN-Daten
const char* ssid = "WLAN_SSID";
const char* password = "WLAN_PASSWD";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(200);
Serial.print(".");
}
Serial.println("Verbunden!");
wifiClient.setInsecure();
if (sender.begin(wifiClient, "https://httpbin.org/ip")) {
// Optional; Falls Header für Authentifizierung o.ä gesetzt werden sollen
// sender.addHeader("Authorization", "Bearer dein_token_hier");
// HTTP-Code der Response speichern
int httpCode = sender.GET();
if (httpCode > 0) {
// Anfrage wurde gesendet und Server hat geantwortet
// Info: Der HTTP-Code für 'OK' ist 200
if (httpCode == HTTP_CODE_OK) {
// Hier wurden die Daten vom Server empfangen
// String vom Webseiteninhalt speichern
String payload = sender.getString();
// Hier kann mit dem Wert weitergearbeitet werden
// ist aber nicht unbedingt notwendig
Serial.println(payload);
}
}else{
// Falls HTTP-Error
Serial.printf("HTTP-Error: ", sender.errorToString(httpCode).c_str());
}
// Wenn alles abgeschlossen ist, wird die Verbindung wieder beendet
sender.end();
}else {
Serial.printf("HTTP-Verbindung konnte nicht hergestellt werden!");
}
}
void loop() {
}
Zum Kapitel springen Hinweise zu HTTPS Anfragen mit Zertifikat
Um die Sicherheit der HTTPS-Verbindungen auf dem ESP8266 zu verbessern, ist es empfehlenswert, das Zertifikat des vertrauenswürdigen Ausstellers - also das CA-Zertifikat - zu verwenden. Dies validiert die Authentizität des Servers, mit dem der ESP8266 kommunizieren soll, und vermindert dadurch potenzielle Sicherheitsrisiken.
Wenn das spezifische Zertifikat des Ausstellers (das CA-Zertifikat) auf dem ESP8266 hinterlegt wird, kann die setCACert()
Methode verwendet werden, um das Zertifikat der HTTP-Anfrage anzufügen.
Zum Kapitel springen Zertifikat beschaffen
Zuerst musst du das Root-Zertifikat des Zertifikat-Ausstellers in einem geeigneten Format beschaffen. Dieses Zertifikat findest du in der Regel auf der Website der Zertifizierungsstelle oder direkt über deinen Browser, indem du die Zertifikatsdetails der HTTPS-Seite anschaust.
Für Webseiten, die beispielsweise von Let's Encrypt verschlüsselt werden, findest du das Root-Zertifikat hier.
Das Root-Zertifikat muss in ein Format gebracht werden, das der ESP8266 verwenden kann, typischerweise das PEM-Format. Dieses Format kann für das Beispiel mit Let's Encrypt beispielweise direkt bezogen werden. Für die meisten Anwendungen auf dem ESP8266, insbesondere wenn Kompatibilität und breite Akzeptanz erforderlich sind, würde ich das aktuelle ISRG Root X1 (selbst-signiert) empfehlen.
Zum Kapitel springen Zertifikat verwenden
Wenn du dir das entsprechende Zertifikat beschafft hast, kannst das Zertifikat anschließend direkt in deinen Arduino-Sketch einfügen, z.B. als String-Variable:
const char* caCert = R"(
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
...
-----END CERTIFICATE-----
)";
Wenn du das Zertifikat in einer Datei auf dem ESP8266 speichern willst, kannst du es beim Start des Programms lesen und in eine Variable laden. Dazu könnte dir das Tutorial Dateien auf dem ESP8266 speichern und lesen: Das SPIFFS Dateisystem weiterhelfen.
Statt vor der eigentlichen HTTP-Request wifiClient.setInsecure();
zu verwenden, kannst du mit einem gültigen Root-CA-Zertifikat stattdessen nun setCACert()
aufrufen. Dies teilt dem ESP8266 mit, das bereitgestellte Zertifikat zu verwenden, um die Identität des Servers über dessen Zertifikat zu verifizieren.
wifiClient.setCACert(caCert);
Anschließend kannst du deine HTTPS-Anfrage wie gewohnt senden. Der ESP8266 wird das Server-Zertifikat gegen das von dir bereitgestellte CA-Zertifikat überprüfen. Dieses Vorgehen erhöht die Sicherheit deiner Anwendungen erheblich, indem es sicherstellt, dass nur authentische und vertrauenswürdige Server mit deinem ESP8266 kommunizieren können.
Produktempfehlungen und -suche in Verbindung mit dem Amazon Partnerprogramm:
¹ Angaben ohne Gewähr. Bei einem Kauf über den Link erhalten wir eine Provision.
Zum Kapitel springen Weitere Informationen
Das Thema SSL/TLS wurde hier nur oberflächlich behandelt und erfordert erweitertes Wissen zum Thema TSL und SSL. Für eine vertiefte Auseinandersetzung mit dem Aufbau und der Verwendung von Zertifikatsketten, empfehle ich mein Tutorial TLS-Sicherheit für MongoDB: Umfassende Anleitung zur Verschlüsselung. Obwohl der Fokus des Tutorials auf MongoDB liegt, findest du dort allgemeine und nützliche Informationen, die dein Verständnis über SSL/TLS-Sicherheit erweitern können. Insbesondere das Kapitel Root-CA Zertifikat kann dir für diesen Beitrag helfen.