Selbstgemacht

Jetzt wird es langsam interessant. Apache ist ein gut erweiterbares System, das so flexibel ist, dass man nicht mal auf das HTTP-Protokoll festgelegt ist. Module können in C geschrieben sein, so wie die oben vorgestellten. In C zu programmieren, ist aber zeitraubend und umständlich, vor allem für Admins, die keine professionellen Software-Entwickler sind. Dank Modulen wie »mod_perl« und »mod_python« lassen sich Apache-Module auch in agileren Sprachen schreiben.

Wie gezeigt, ist Apache schon sehr flexibel, was die Zugangskontrolle betrifft, aber er berücksichtigt beispielsweise keine Tageszeiten. Als Beispiel für ein eigenes Authentifizierungsschema soll der Fall dienen, dass eine Firma in zwei Schichten arbeitet, und jede nur die Daten ihrer Schicht ansehen kann. Dazu aktivieren Sie zunächst das Perl-Modul.

LoadModule perl_module modules/mod_perl.so

Mittels Mod-Perl können Sie in jede Phase der Apache-Request-Verarbeitung eingreifen, indem Sie dafür ein kleines Perl-Modul schreiben. Im Beispielfall soll es, wie gehabt, Benutzernamen und Passwort abgleichen, aber auch die Tageszeit überprüfen. Gleichzeitig weist es an Samstagen und Sonntagen jeden ab.

Listing 6

Zugriffskontrolle mit Mod-Perl

package ByShiftAuth;
use strict;
use warnings;
use Apache2::Access ();
use Apache2::RequestUtil ();
use Apache2::Const -compile => qw(OK HTTP_UNAUTHORIZED AUTH_REQUIRED);
use DBI;
use Digest::MD5 qw( md5_hex );
sub handler {
my $r = shift;
# See if this is the initial request or not, if it isn't
# they are already authentication and we just need to reset
# the username
if( !$r->is_initial_req ) {
    if( defined $r->prev ) {
        $r->user( $r->prev->user );
    }
   return Apache2::Const::OK;
}
# Check to see if it's a weekend
my $day_of_week = (localtime(time))[6];
if( $day_of_week == 0 or $day_of_week == 6 ) {
    return Apache2::Const::HTTP_UNAUTHORIZED;
}
# Get the username and password
my ($rc, $password) = $r->get_basic_auth_pw();
my $user = $r->user;
unless ( $user and $password ) {
    $r->note_basic_auth_failure;
    return( Apache2::Const::AUTH_REQUIRED );
}
# Now let's connect to our database and compare things in
# our database we're going to store passwords as MD5 digests
my $dbh = DBI->connect('dbi:Pg:dbname=admin', 'apache', 'secret')
    or die "Cannot connect to database: $!";
my $sth = $dbh->prepare( qq{
    SELECT password FROM users WHERE user = ? AND
       current_time BETWEEN shift_begin AND shift_end });
$sth->execute( $user );
my $db_password = $sth->fetchrow;
$sth->finish;
# Make sure we found a password for this user, if we don't
# it means they don't exist or their shift isn't in progress
if( !$db_password ) {
    $r->note_basic_auth_failure;
    return( Apache2::Const::AUTH_REQUIRED );
}
# Check to make sure the passwords match
if( md5_hex( $password ) ne $db_passwd ) {
    $r->note_basic_auth_failure;
    return( Apache2::Const::AUTH_REQUIRED );
}
return( Apache2::Const::OK );
}

Speichern Sie die Datei irgendwo in Perls Include-Pfad »@INC« unter dem Namen »ByShiftAuth.pm« . Wollen Sie lieber einen anderen Speicherort, so geht das auch, aber dann müssen Sie ihn in der Apache-Konfiguration eintragen:

<Perl>
use lib qw( /Pfad/zu/ByShiftAuth.pm );
</Perl>

Um das Skript mit Apache zu verwenden, sind ein paar weitere Zeilen nötig:

<Location /admin>
  AuthType Basic
  AuthName "Admin Pages"
  PerlAuthenHandler ByShiftAuth
  Require valid-user
</Location>

Nachdem es die nötigen Module geladen hat, definiert das Skript in Listing 6 den Apache-Handler. Als erstes überprüft es, ob es sich um den ursprünglichen Request oder einen internen Redirect handelt (Zeile XXX). Ist es nicht die originale Anfrage, hat das System sie schon authentifiziert und das Modul kann die Kontrolle wieder abgeben.

Als nächstes überprüft das Modul, ob es sich um ein Wochenende handelt. Ist das der Fall, weist es kurzerhand jeden ab (Zeile XXX). Andernfalls fordert es den Benutzer auf, Username und Passwort einzugeben. Fehlt eine der beiden Angaben liefert das Modul den Wert »AUTH_REQUIRED« zurück, was dazu führt, dass der Eingabedialog für den Benutzer wieder erscheint.

Das Skript verbindet sich mit der Datenbank und liest dort das Passwort aus. Die Anfrage setzt voraus, dass in der gleichen Tabelle auch die Zeiten für Schichtbeginn und -ende stehen. Sie ist so formuliert, dass sie kein Ergebnis liefert, wenn Sie außerhalb dieser Zeiten an die Datenbank gestellt wird. In einem echten Anwendungsfall sollte man dem Benutzer den Grund mitteilen, warum er sich nicht einloggen kann, statt ihn es einfach wieder und wieder probieren zu lassen.

Im letzten Schritt vergleicht das Skript den MD5-Hash des Passworts mit dem Wert aus der Datenbank. Schlägt der Vergleich fehl, bekommt der Anwender wieder die Eingabemaske präsentiert. Stimmen die Werte überein, gibt das Skript »OK« zurück, womit Apache den Benutzer als authentifiziert ansieht.

Fazit

Diese kurzen Beispiele demonstrieren einige Möglichkeiten, die eigene Website mit Benutzernamen und Passwörtern abzusichern. Schauen Sie sich mal die entsprechende Dokumentation auf der Apache-Site an, es gibt noch viele Optionen zu entdecken. Achja, und schreiben Sie keine Passwörter auf Post-Its, das ist wirklich eine schlechte Idee!

Ähnliche Artikel

comments powered by Disqus
Mehr zum Thema

Benutzerdaten in Webanwendungen übernehmen

Benutzerdatenbanken wie ein ein zentraler LDAP-Server oder dedizierte Identity-Management-Lösungen wie FreeIPA oder Active Directory enthalten eine Menge an Informationen über die darin gespeicherten Benutzer. Wir zeigen eine Methode, wie Webanwendungen sehr einfach auf diese Informationen zurückgreifen können.

Artikel der Woche

Eigene Registry für Docker-Images

Wer selber Docker-Images herstellt, braucht auch eine eigene Registry. Diese gibt es ebenfalls als Docker-Image, aber nur mit eingeschränkter Funktionalität. Mit einem Auth-Server wird daraus ein brauchbares Repository für Images. (mehr)
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Konfigurationsmanagement

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit CFengine
  • mit dem Nix-System
  • mit Containern
  • mit anderer Konfigurationsmanagement-Software

Ausgabe /2020