Skip to content

INN: Authentifizierung gegen MySQL-Datenbank

INN bietet vielfältige Möglichkeiten der Benutzerauthentifizierung an. Wenn man einer größeren Anzahl von Benutzern einen Zugang einräumen will, bietet es sich an, die notwendigen Daten - Benutzerkennung, Paßwort, etc. - in einer Datenbank zu halten, bspw. in einer MySQL-Datenbank.

Eine denkbare Lösung dafür, die neben Benutzerkennung und Paßwort auch Namen und E-Mail-Adresse des Benutzers erfaßt sowie ein Flag für aktive/inaktive Benutzer und eine Trennung nach verschiedenen Zugriffsstufen kennt sowie den Zeitpunkt des letzten Logins festhält, möchte ich hier vorstellen. Dazu gehört über das hier vorgestellte Script für den INN hinaus natürlich noch ein passendes (Web-)Interface, mit dem Benutzer angelegt und gelöscht sowie Paßworte geändert werden können etc.

Die Datenbankstruktur sieht folgendermaßen aus:

    CREATE TABLE IF NOT EXISTS `users` (
      `userid` int(11) NOT NULL auto_increment,
      `user` varchar(16) collate latin1_bin NOT NULL default '',
      `password` varchar(16) collate latin1_bin NOT NULL default '',
      `active` tinyint(1) NOT NULL default '1',
      `username` varchar(60) collate latin1_bin default NULL,
      `usermail` varchar(60) collate latin1_bin default NULL,
      `domain` varchar(40) collate latin1_bin default '<EDITME>',
      `llo` date default NULL,
      PRIMARY KEY  (`userid`),
      UNIQUE KEY `user` (`user`)
    );

Die Felder sollten weitgehend selbsterklärend sein; "llo" steht für "last logged in".

Die Module DBI und Time::Localtime werden benötigt; außerdem müssen natürlich die Zugangsdaten für die Datenbank definiert werden:

  1.     use DBI;
  2.     use Time::localtime;
  3.  
  4.     ### DB Vars - EDIT ME!
  5.     $conf{'dbdriver'} = "mysql";
  6.     $conf{'dbhost'}   = "localhost";
  7.     $conf{'database'} = "";
  8.     $conf{'dbuser'}   = "";
  9.     $conf{'dbpw'}     = "";
  10.     $conf{'dbtable'}  = "";
  11.     $conf{'actcheck'} = 1;

Der eigentliche Zugriff auf die Datenbank kommt in die Subroutine "authenticate", die dann vom INN aufgerufen wird:

  1.     ### DB init
  2.     my $dbs = sprintf('DBI:%s:database=%s;host=%s',$conf{'dbdriver'},$conf{'database'},$conf{'dbhost'});
  3.     my $dbhandle = DBI-&gt;connect($dbs, $conf{'dbuser'}, $conf{'dbpw'}, { PrintError =&gt; 1 });
  4.  
  5.     ### Query database and disconnect.
  6.     my(@result);
  7.     # quote SQL
  8.     my $sql_user = $dbhandle-&gt;quote($attributes{username});
  9.     my $sql_pass = $dbhandle-&gt;quote($attributes{password});
  10.     my $query = sprintf("SELECT domain FROM %s.%s WHERE user = %s AND password = %s",$conf{'database'},$conf{'dbtable'},$sql_user,$sql_pass);
  11.     if ($conf{'actcheck'}) {
  12.       $query .= ' AND active = 1';
  13.     };
  14.     my $dbquery = $dbhandle-&gt;prepare($query);

Wenn die Abfrage erfolgreich verlief, es also einen passenden Benutzer mit passenden Paßwort gibt, wird der Zeitpunkt des letzten Logins in der Datenbank aktualisiert:

  1.     if ($dbquery-&gt;execute()) {
  2.      @result = $dbquery-&gt;fetchrow_array;
  3.      $dbquery-&gt;finish;
  4.      if (@result) {
  5.       # log timestamp
  6.       my $tm = localtime;
  7.       my $today = sprintf('%04d-%02d-%02d', $tm-&gt;year+1900, ($tm-&gt;mon)+1, $tm-&gt;mday);
  8.       $query = sprintf("UPDATE %s.%s SET llo = '%s' WHERE user = %s",$conf{'database'},$conf{'dbtable'},$today,$sql_user);
  9.       $dbquery = $dbhandle-&gt;prepare($query);
  10.       $dbquery-&gt;execute();
  11.       $dbquery-&gt;finish;
  12.      };
  13.     };
  14.     $dbhandle-&gt;disconnect;

Danach ist nur noch entsprechend zu reagieren:

  1.     ### check password and respond appropriate
  2.     if (@result) {
  3.      my $user = $attributes{username} . '@' . $result[0];
  4.      return (281, 'Authentication successful: '.$user, $user);
  5.     } else {
  6.      return (481, 'Authentication failure');
  7.     }

Das komplette Perl-Script gibt's in meinem Git-Repository.

Eingebunden wird dieses Perl-Script in die readers.conf des INN als Authentification Group:

    auth "users-mysql" {
        hosts: *
        perl_auth: "/usr/lib/news/bin/auth/passwd/perl_mysql"
    }

Es liefert dann eine Benutzerkennung der Form user@domain zurück; die domain kann dann in folgenden Access Groups referenziert werden:

    access "customers" {
        users: "*@customer.news.host.example"
        newsgroups: "*, !internal.*, !special.*"
        access: "RP"
    }

Trackbacks

Keine Trackbacks

Kommentare

Ansicht der Kommentare: Linear | Verschachtelt

Frank L am :

Frank L

Great script, just what I have been looking for for INN.

One question, you mention this also includes a suitable (web) interface with which users can be created and deleted and passwords changed. Where might I find that?

Thomas Hochstein am :

Thomas Hochstein

That’s left as an exercise to the reader. :-)

Seriously, this goes beyond the scope of this article and is not a difficult task in the end. The script will need password protection, input fields for the corresponding data and must be able to save and read them. There are lots of tutorials for these tasks as they are also needed for an address database or whatever else you might want to do with a database.

Kommentar schreiben

HTML-Tags werden in ihre Entities umgewandelt.
Markdown-Formatierung erlaubt
Standard-Text Smilies wie :-) und ;-) werden zu Bildern konvertiert.
BBCode-Formatierung erlaubt
Gravatar, Identicon/Ycon Autoren-Bilder werden unterstützt.
Formular-Optionen
tweetbackcheck