ESP8266 Webserver - HTTP-Authentifizierung mit Benutzername und Passwort

von cooper.bin
veröffentlicht am 25.08.2024 aktualisiert am 26.08.2024

Im Internet spielt die Authentifizierung eine zentrale Rolle. Um sicherzustellen, dass nur autorisierte Benutzer Zugriff auf bestimmte Ressourcen haben, werden diese durch das Abfragen von Anmeldedaten abgesichert. Diese scheinbar einfache, aber dennoch effektive Sicherheitsmaßnahme ist auch auf einem ESP8266 Webserver anwendbar. Durch das Implementieren eines Logins können Daten vor unbefugtem Zugriff geschützt werden.

ESP8266 Login Maske Formular ><

Zum Kapitel springen Vergleich mit klassischen Webservern

Bei traditionellen Webservern wie Apache oder NGINX kann eine Authentifizierung unter anderem über einfache .htaccess-Dateien geregelt werden. Diese Dateien definieren Zugangsbeschränkungen und fordern vom Benutzer eine Anmeldung, bevor er auf geschützte Inhalte zugreifen kann. Hierbei kommt die Basis-Authentifizierung (Basic HTTP Authentication) zum Einsatz, wobei die Anmeldedaten in einem bestimmten Verzeichnis des Servers gespeichert sind und durch die .htaccess-Datei gesteuert werden.

Auf einem ESP8266 Webserver, der aufgrund seiner Ressourcen erheblich eingeschränkter ist als ein vollwertiger Webserver, gibt es keine .htaccess-Dateien im herkömmlichen Sinne. Stattdessen kann die Authentifizierung schnell und einfach direkt im Code implementiert werden, sodass die Funktionalität ähnlich bleibt: Der Benutzer wird zur Eingabe von Benutzernamen und Passwort aufgefordert, bevor er auf geschützte Inhalte zugreifen kann.

Produktempfehlungen und -suche in Verbindung mit dem Amazon Partnerprogramm:

¹ Angaben ohne Gewähr. Bei einem Kauf über den Link erhalten wir eine Provision.

Trotz der Unterschiede in der Infrastruktur kann eine ähnliche, einfache und effektive Authentifizierungsebene direkt auf dem ESP8266-Webserver aufgesetzt werden.

Zum Kapitel springen Implementierung der HTTP-Authentifizierung auf dem ESP8266

Für dieses Beispiel greife ich auf das Code-Snippet aus dem Tutorial ESP8266 Webserver mit echten HTML Dateien. zurück. Es ist wichtig, dass du diesen Code verstehst und auf den ESP8266 hochlädst, bevor du die folgenden Code-Snippets einbindest.

Produktempfehlungen und -suche in Verbindung mit dem Amazon Partnerprogramm:

¹ Angaben ohne Gewähr. Bei einem Kauf über den Link erhalten wir eine Provision.

Um die Basis-Authentifizierung auf einem ESP8266 Webserver zu implementieren, erstellen wir eine Funktion, die bei jeder Anfrage die Anmeldedaten überprüft.

Zunächst definieren wir dafür einen Benutzernamen und ein Passwort, die optional durch die authenticate-Methode der AsyncWebServerRequest-Klasse verifiziert werden können.

Diese Methode wird also nicht automatisch ausgeführt, sondern muss explizit in den gewünschten Routen aufgerufen werden. Falls die Authentifizierung fehlschlägt, gibt die Methode false zurück und verhindert das Anzeigen der Seite.

const char* http_username = "admin";
const char* http_password = "1234";

bool handleAuthentication(AsyncWebServerRequest *request) {
  if (!request->authenticate(http_username, http_password)) {
    request->requestAuthentication();
    return false;
  }
  return true;
}

Der Aufruf der Authentifizierungsfunktion kann nun in nur einer Zeile erfolgen:

if (!handleAuthentication(request)) return;

Diese Zeile kann in jeder Route eingefügt werden, die abgesichert werden soll. Dadurch wird die Authentifizierung gleich zu Beginn der Routenverarbeitung geprüft. In diesem Beispiel sichern wir alle Routen des Servers ab, sowohl die Server-Routen als auch die Datei-Routen.

Die Startseite mit der vorgeschalteten Authentifizierungsprüfung sieht dann wie folgt aus:

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    // Hier findet die Prüfung der vorher festgelegten Zugangsdaten statt
    if (!handleAuthentication(request)) return;
    request->send(LittleFS, "/index.html", "text/html");
});

Beim ersten Besuch des Webservers und der geschützten Route werden die Anmeldedaten abgefragt.

Benutzername: admin
Passwort: 1234

Zum Kapitel springen Vollständiger Beispielcode

//
// Einfacher Webserver der Dateien aus dem LittleFS (Filesystem) ausliefert und mit einem Login abgesichert ist
// cooper.bin @ makesmart.net
// mehr Infos unter: https://makesmart.net/blog/read/esp8266-webserver-absichern-mit-basic-http-auth
//

void setupServerRoutes();
void setupFilePaths();

// WLAN
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>

// Webserver 
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>

// Filesystem
#include <LittleFS.h>

// Standard HTTP-Port 80
AsyncWebServer server(80);

// WLAN-Zugangsdaten
const char* ssid      = "ssid";
const char* password  = "password";

// Login-Zugangsdaten für die HTTP-Authentifizierung
const char* http_username   = "admin";
const char* http_password   = "1234";

// Hostname des ESPs -> http://makesmartesp.local/
const char* espHostname   = "makesmartesp";

// Was passiert, wenn eine Seite nicht gefunden werden kann
// Es wird die Datei `404.html` ausgeliefert
void notFound(AsyncWebServerRequest *request) {
    AsyncWebServerResponse* response = 
      request   ->  beginResponse(LittleFS, "/404.html", "text/html");
      response  ->  setCode(404);
      request   ->  send(response);
}

// Funktion zum Prüfen der Zugangsdaten für die HTTP-Authentifizierung
bool handleAuthentication(AsyncWebServerRequest *request) {
  if (!request->authenticate(http_username, http_password)) {
    request->requestAuthentication();
    return false;
  }
  return true;
}


void setup() {
  delay(500);
  Serial.begin(115200);
  Serial.println();
  delay(500);

  // Dateisystem initialisieren
  if(LittleFS.begin()){
    Serial.println("Dateisystem: Initialisiert");
  }else{
    Serial.println("Dateisystem: Fehler beim Initialisieren");
  }
  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
      Serial.println("WLAN Verbindung fehlgeschlagen");
      return;
  }

  Serial.print("Verbunden! IP-Adresse: "); Serial.println(WiFi.localIP());

  // Starten des mDNS-Servers
  if ( !MDNS.begin(espHostname) ) {             
    Serial.println("Fehler beim Staren des mDNS-Servers!");
  }

  // Server Routen werden in einer eigenen Funktion definiert
  setupServerRoutes();
  // Datei Routen werden in einer eigenen Funktion definiert
  setupFilePaths();

  server.begin();
}

void loop() {
  MDNS.update();
}


void setupServerRoutes(){
  // Als Document-Root gilt der Ordner `data`; 
  // siehe: https://makesmart.net/blog/read/dateien-auf-dem-esp8266-speichern-und-lesen-das-spiffs-dateisystem
  // Alle Pfade zu Dateien müssen relativ vom Ordner "data" definiert werden

  // Datei `index.html` wird ausgeliefert
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    // Hier findet die Prüfung der vorher festgelegten Zugangsdaten statt
    if (!handleAuthentication(request)) return;
    request->send(LittleFS, "/index.html");
  });

  server.onNotFound(notFound);
  
}

void setupFilePaths(){

  // In `server.on` wird die Webserver-Route definiert
  // in der Logik wird dann die CSS Datei aus dem LittleFS ausgeliefert: `assets/css/style.css`
  server.on("/assets/css/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
    if (!handleAuthentication(request)) return;
    request->send(LittleFS, "/assets/css/style.css", "text/css");
  });

  // Gleiches mit einer Javascript-Datei
  server.on("/assets/js/script.js", HTTP_GET, [](AsyncWebServerRequest *request){
    if (!handleAuthentication(request)) return;
    request->send(LittleFS, "/assets/js/script.js", "application/javascript");
  });

  // Gleiches mit einem PNG-Bild
  server.on("/assets/images/favicon-96.png", HTTP_GET, [](AsyncWebServerRequest *request){
    if (!handleAuthentication(request)) return;
    request->send(LittleFS, "/assets/images/favicon-96.png", "image/png");
  });
  
}

Zum Kapitel springen Wo wird der Login gespeichert?

Die HTTP-Basis-Authentifizierung speichert den Login-Zustand nicht direkt in einer Session oder einem Cookie. Stattdessen sendet der Browser bei jeder Anfrage die Anmeldedaten, also Benutzername und Passwort, erneut als Teil des HTTP-Headers. Diese Anmeldedaten bleiben in der Regel während der gesamten Sitzung des Benutzers im Browser zwischengespeichert, sodass der Benutzer nicht bei jeder Anfrage erneut zur Eingabe aufgefordert wird. Die "Sitzung" in diesem Fall hängt also vom Browser ab.

Solange der Browser geöffnet bleibt und die Anmeldedaten zwischengespeichert sind, bleibt der Benutzer angemeldet. Wenn der Browser geschlossen oder die zwischengespeicherten Daten gelöscht werden, muss der Benutzer die Anmeldedaten erneut eingeben.

Zum Kapitel springen Sicherheit der HTTP-Basis-Authentifizierung

Die HTTP-Basis-Authentifizierung ist einfach, aber nicht besonders sicher, da die Anmeldedaten bei jeder Anfrage als Klartext (Base64-kodiert) über das Netzwerk gesendet werden. Dies macht sie anfällig für Angriffe, insbesondere in ungesicherten HTTP Verbindungen.

Sicherheitstipps:

  • Verwende HTTPS: Durch die Verwendung von HTTPS wird die gesamte Kommunikation, einschließlich der Anmeldedaten, verschlüsselt und schützt vor Abhörangriffen.
  • Beschränke den Zugriff: Stelle sicher, dass der Webserver nur für autorisierte IP-Adressen oder über ein gesichertes Netzwerk zugänglich ist.
  • Schütze den Quellcode: Da die Anmeldedaten im Quellcode hinterlegt sind, ist es wichtig, den Code vor unberechtigtem Zugriff zu schützen.

Unter der Annahme, dass der Quellcode sicher ist und HTTPS verwendet wird, kann die HTTP-Basis-Authentifizierung für viele einfache Anwendungen als ausreichend sicher betrachtet werden. Für Anwendungen, die ein höheres Sicherheitsniveau erfordern, sollte jedoch eine stärkere Authentifizierungsmethode in Betracht gezogen werden.

Die Implementierung einer Basic HTTP Auth auf dem ESP8266 ist eine praktische Methode, um den Zugriff auf deinen Webserver abzusichern. Während diese Methode einfach zu implementieren ist, sollten ihre Sicherheitsbeschränkungen berücksichtigt werden, insbesondere in ungesicherten Netzwerken. Durch den Einsatz von HTTPS und weiteren Maßnahmen kann jedoch ein angemessenes Sicherheitsniveau erreicht werden.


cooper.bin Avatar

cooper.bin

Unterstütze mich und meine Arbeit, so kann ich weiter meiner Leidenschaft nachgehen. Ich lege viel Wert auf Qualität und stecke daher sehr viel Zeit in meine Beiträge. Wenn sie dir gefallen kannst du dir gerne auch meine anderen Artikel anschauen.

Mit PayPal unterstützen

Ich bin auf dem makesmart Discord-Server aktiv. Dort bin ich auch relativ gut erreichbar.

Teile diesen Beitrag



Diese Artikel könnten dich auch interessieren

ESP8266 Webserver: GET-Variablen auslesen

GET-Parameter sind Variablen, die über die URL übergeben werden. Diese Variablen können auf einem ESP8266 ausgelesen werden, um bestimmte Aktionen in der Software auszulösen.

cooper.bin am 17.02.2024

ESP8266 - Ein einfacher Webserver mit mDNS

Während Webserver wie Apache2 oder NGNIX auf Rechnern laufen, kann man auch auf einem ESP8266 einen Webserver verwenden. In diesem Tutorial werden wir ein Grundgerüst implementieren.

cooper.bin am 13.02.2024

ESP8266 D1 Mini WLAN-Relais mit HTTP API

Mit diesem einfachem Webserver auf dem ESP8266 mit HTTP API kannst du ein Relais smart machen! Steuere das Relais über deinen Webbrowser oder automatisiert durch andere Dienste.

cooper.bin am 20.02.2024

ESP8266 Webserver mit echten HTML Dateien

Mit dem ESPAsyncWebserver kann man einen dateibasierten Webserver auf dem ESP8266 realisieren. Dieser kann HTML, CSS, Javascript und jede andere Art von Datei ausliefern.

cooper.bin am 28.04.2024

ESP8266 Websocket Server für Echtzeitkommunikation

Mit einem Websocket-Server auf dem ESP8266 kann man Daten in Echtzeit austauschen. Im Gegensatz zu HTTP kann der Server den Client über neue Events benachrichtigen, ohne vorher angefragt zu werden.

cooper.bin am 02.05.2024