Sessions en perl sur serveur Apache

30/05/2005

L'objectif est de gérer des sessions web sur serveur Apache à partir de perl. Une fois identifié au moyen d'un formulaire, on assigne au visiteur un cookie de session puis on alimente en interne différentes variables.

Identification

Formulaire XHTML

Tout commence par le formulaire suivant :

<form action="/cgi-bin/login.cgi" method="post">
<fieldset id="identification">
<legend>Identification</legend>
<dl>
<dt><label for="login">Login</label></dt>
<dd><input type="text" name="login" id="login" size="10" /></dd>
<dt><label for="pwd">pwd</label></dt>
<dd><input type="password" name="pwd" id="pwd" size="10" /></dd>
</dl>
<p><input type="submit" value="Login" />
<input type="submit" value="Logout" name="logout" /></p>
</fieldset>
</form>

Ce qui nous donne, une fois stylé :

Identification

Le code XHTML est validé et sémantiquement correct et accessible. Il permet à l'utilisateur de rentrer son identifiant et son mot de passe. Un bouton est de surcroît prévu pour fermer la session.

Script d'identification

Nous allons utiliser le module CGI::Session pour ce qui est des sessions, et nous écrirons directement les cookies plutôt que de dépendre de CGI::Cookie. Nous faisons ici une authentification simple d'une seule personne mais si nous avions plus d'utilisateurs ou un système hiérarchique complexe, nous utiliserions une table de hashage stockée en local (avec par exemple use SDBM_File; puis tie(%pwd, 'PWD_file', 'c:/apache/dbs/pwd.sdbm', O_RDWR|O_CREAT, 0666); sans oublier le untie %pwd; en fin de traitement) ou un fichier XML mis hors zone publique du serveur. Il n'est pas assigné de date au cookie de telle sorte qu'il expire automatiquement une fois le browser fermé.

#!perl
# All by HAbeTT
# Login identification

use CGI::Session;
use CGI;

# Récuperation parametre action
$query = new CGI;

if ($query->param('logout')) {
  # Utilisateur voulant fermer sa session manuellement
  # Récupération de la session
  $cookie = $query->cookie(-name => "session");
  if ($cookie) {
    CGI::Session->name($cookie);
  }
  # Expiration de la session serveur
  $session = new CGI::Session("driver:File",$cookie,{'Directory'=>"d:/apache/tmp"}) or die "$!";
  $session->clear();
  $session->expire('+2h');
  # Destruction du cookie de session
  print "Set-Cookie: session=$id; domain=.$host; path=/; expires=Sat, 8-Oct-2001 01:01:01 GMT\n";
  # Retour automatique à la page d'identification
  print "Location: ".$ENV{'HTTP_REFERER'}."\n\n";
  exit(0);
}

# Initiation de la session
$session = new CGI::Session("driver:File",undef,{'Directory'=>"d:/apache/tmp"});

# Récupération de l'identifiant et du mot de passe
$login = $query->param('login');
$login =~ s/(?:\012\015|\012|\015)//g;
$pwd = $query->param('pwd');
$pwd =~ s/(?:\012\015|\012|\015)//g;

# Test de validité de la paire et assignation d'une variable de status.
if (($login eq 'Admin') and ($pwd eq 'Password')) {
  $zstatus = 'administrator';
} elsif (($login eq 'Private') and ($pwd eq 'Soldier')) {
  $zstatus = 'private';
} else {
  print "Content-type: text/plain\n\nNope !";
  exit(0);
}

# Inscription de la variable dans la session sur le serveur
$session->param('status',$zstatus);
$session->expire('+2h');

# Envoi du cookie reliant l'utilisateur à sa session serveur
$id = $session->id();
$host = $ENV{'HTTP_HOST'};
print "Set-Cookie: session=$id; domain=.$host; path=/\n";

# Retour à la page d'accueil
print "Location: ".$ENV{'HTTP_REFERER'}."\n\n";

# Petit nettoyage du dossier des sessions
if (int(rand(10)) == 1) {
  # expire old sessions
  $filez = "d:/apache/tmp/*";
  while ($file = glob($filez)) {
    @stat=stat $file; 
    $days = (time()-$stat[9]) / (60*60*24);
    unlink $file if ($days > 3);
  }
}

exit(0);

Récupération des variables de sessions

Dans les scripts où l'on doit savoir qui s'est identifié et quel est son status, il suffira du code suivant :

use CGI::Session;
use CGI;

$query = new CGI;
$cookie = $query->cookie(-name => "session");
if ($cookie) {
  CGI::Session->name($cookie);
}
$session = new CGI::Session("driver:File",$cookie,{'Directory'=>"d:/apache/tmp"}) or die "$!";
$status = $session->param('status');

Libre à vous de stocker autant de variables de session que vous voulez sur le serveur. C'est une stratégie plus sûre que de stocker de telles informations dans des cookies clients car vous gardez ainsi la main sur les données. Si un utilisateur malicieux tombe par chance ou autre sur un identifiant de session correct, il n'en tirera pas grand chose car la session expirera de toute façon.

menu principal