Auto_restrict 2.0: un fichier pour les verrouiller tous.

Aujourd'hui, histoire de ressuciter un peu, je vous propose une amélioration de auto_restrict, le fichier php qu'il suffit d'inclure dans une page pour en restreindre l'accès.

J'ai beaucoup utilisé ce petit fichier dans mes projets mais il lui manquait une feature importante: la coche "rester connecté". 

Désormais, il gère un cookie dont on définit la durée et le nom dans la config et qui éviter d'avoir à chaque fois le formulaire de login.

En cas de déconnexion, le cookie est viré. 

J'ai également amélioré le rendu du formulaire sur les mobiles, ajouté la possibilité de choisir son login lors de la création et déplacé la variable login dans le fichier pass.php.

 

 

 


 

Le zip contient un exemple complet et simple:

  • un fichier index.php qui appelle auto_restrict.php
  • un fichier login_form.php contenant le formulaire servant à se logger
  • auto_restrict.php (le fichier qu'il suffit d'inclure)

Lors de la première utilisation du script, Auto_restrict va proposer de créer le login et le passe via un formulaire: on tape les identifiants de connexion voulus et le fichier pass.php est créé automatiquement avec le passe crypté et le login.

Lorsqu'on charge ensuite la page qui appelle auto_restrict, cette dernière vérifie si les variables de session sont présentes et si elles sont correctes ou si le cookie est présent.

Afin d'éviter de se faire pécho sa session, j'ai ajouté une variable contenant toutes les infos de l'utilisateur (ip+navigateur) cryptée; j'ai récupéré les fonctions de cryptage sur info-3000.com merci au passage .

Si un problème est détecté, on dégage les variables de session éventuelles, on la détruit, on include le formulaire de login et on arrête tout.

 

Quand on remplit le formulaire et qu'on l'envoie, c'est encore auto_restrict qui prend la main et gère la connexion: si les login/passe correspondent à ceux fournis en config, on crée la session, sinon, on considère qu'il y a un problème... et on include le formulaire

    // ------------------------------------------------------------------
    // configuration    
    // ------------------------------------------------------------------
    $auto_restrict['error_msg']='Erreur - impossible de se connecter.';// utilisé si on ne veut pas rediriger
    $auto_restrict['cookie_name']='auto_restrict';// nom du cookie
    $auto_restrict['encryption_key']='abcdef';// clé pour le cryptage de la chaine de vérification
    $auto_restrict['session_expiration_delay']=1;//minutes
    $auto_restrict['cookie_expiration_delay']=360;//days
    $auto_restrict['login']='login'; // caractères alphanum + _ et .
    $auto_restrict['redirect_error']='index.php';// si précisé, pas de message d'erreur
// ---------------------------------------------------------------------------------
// sécurisation du passe: procédure astucieuse de JérômeJ (http://www.olissea.com/)
if(file_exists('pass.php')) include('pass.php');
if(!isset($auto_restrict['pass'])){
    if(isset($_POST['pass'])&&isset($_POST['login'])&&$_POST['pass']!=''&&$_POST['login']!=''){ # Création du fichier pass.php
        $salt = md5(uniqid('', true));
        file_put_contents('pass.php', '<!--?php $auto_restrict["login"]="'.$_POST['login'].'";$auto_restrict["salt"] = '.var_export($salt,true).'; $auto_restrict["pass"] = '.var_export(hash('sha512', $salt.$_POST['pass']),true).'; ?-->');
        include('login_form.php');exit();
    }
    else{ # On affiche un formulaire invitant à rentrer le mdp puis on exit le script
        include('login_form.php');exit();
    }
}
// ---------------------------------------------------------------------------------


// ------------------------------------------------------------------

// ------------------------------------------------------------------
// gestion de post pour demande de connexion
// si un utilisateur tente de se loguer, on gère ici
// ------------------------------------------------------------------   
if (isset($_POST['login'])&amp;&amp;isset($_POST['pass'])){
    log_user($_POST['login'],$_POST['pass']);
    if (isset($_POST['cookie'])){setcookie($auto_restrict['cookie_name'],sha1($_SERVER['HTTP_USER_AGENT']),time()+$auto_restrict['cookie_expiration_delay']*1440);}
}

// ------------------------------------------------------------------   
// si pas de demande de connexion on verifie les vars de session
// et la duree d'inactivité de la session
// si probleme,on include un form de login.
// ------------------------------------------------------------------
if (!is_ok()){session_destroy();include('login_form.php');exit();} 
// ------------------------------------------------------------------
// demande de deco via la variable get 'deconnexion'
// ------------------------------------------------------------------   
if (isset($_GET['deconnexion'])){log_user('dis','connect');}
// ------------------------------------------------------------------   

Pour la partie fonctions:

    function is_ok(){
        // vérifie et compare les variables de session
        // en cas de problème on sort/redirige en détruisant la session
        global $auto_restrict;
        $expired=false;
        if (isset($_COOKIE[$auto_restrict['cookie_name']])&&$_COOKIE[$auto_restrict['cookie_name']]==sha1($_SERVER['HTTP_USER_AGENT'])){return true;}
        if (!isset($_SESSION['id_user'])){return false;}
        if ($_SESSION['expire']<time()){$expired=true;}
                $sid=Decrypte($_SESSION['id_user'],$auto_restrict['encryption_key']);
        $id=id_user();
        if ($sid!=$id || $expired==true){// problème
            return false;
        }else{ // tout va bien
            //on redonne un délai à la session
            $_SESSION['expire']=time()+(60*$auto_restrict['session_expiration_delay']);
            return true;
        }
    }
function log_user($login_donne,$pass_donne){
    //cree les variables de session
    global $auto_restrict;
    if ($auto_restrict['login']==$login_donne &amp;&amp; $auto_restrict['pass']==hash('sha512', $auto_restrict["salt"].$pass_donne)){
        $_SESSION['id_user']=Crypte(id_user(),$auto_restrict['encryption_key']);
        $_SESSION['login']=$auto_restrict['login']; 
        $_SESSION['expire']=time()+(60*$auto_restrict['session_expiration_delay']);
        return true;
    }else{
        exit_redirect();
        return false;
    }
}

function redirect_to($page){header('Location: '.$page); }
function exit_redirect(){
    global $auto_restrict;
    @session_unset();
    @session_destroy();
    setcookie($auto_restrict['cookie_name'],'',time()+1);
    if ($auto_restrict['redirect_error']&amp;&amp;$auto_restrict['redirect_error']!=''){
            redirect_to($auto_restrict['redirect_error']);
    }else{exit($auto_restrict['error_msg']);}
}</pre>
        <p style="text-align: center;">
            <img alt="" src="http://www.warriordudimanche.net/data/images/auto-restrictcapt2.png" style="text-align: center; width: 252px; height: 349px;" /></p>
    </div>
    <hr />
    <p>
        On peut toujours complexifier le tout en&nbsp;</p>
    <ul>
        <li>
            sécurisant les données post,</li>
        <li>
            en faisant un ban provisoire des ip+navigateur qui cherchent à se logger sans succès trop de fois,&nbsp;</li>
        <li>
            en gérant plusieurs logins/mdp (via un fichier xml ou une BDD...)</li>
    </ul>
    <p>
        Toutefois, je ne voulais pas compliquer l'utilisation sans raison.</p>
    <p>
        &nbsp;</p>
    <p>
        Comme toujours,&nbsp;<a href="http://files.warriordudimanche.net/zip/auto_restrict.zip">le zip est par là</a>&nbsp;.</p>
    <p>
        &nbsp;</p>
</div>
<div>
    &nbsp;</div>

 

❝ 8 commentaires ❞

1  empo le

Hello,

étant une grosse buse en dev je souhaiterais mettre en place ton script pour sécurise une parti admin d'un site web hors quand le formulaire est validé je ne voit ou mettre la page vers laquelle rediriger vers mon dashbord d'admin !
je vois bien : $auto_restrict['redirect_error']='index.php';
qui redirige quand il y une erreur !

Ou je n'ai rien compris !

Un grand merci pour ton site/blog/... je viens de te découvrir via les liens de sebsauvage.

 
2  Bronco le

Salut
En fait, l'utilisation est très simple: il suffit d'inclure auto_restrict au début de la page à protéger (ou de toutes les pages de ton espace admin)
<?php include('auto_restrict.php'); ?>
La première page appelée renvoie vers le formulaire de login et après la connexion, auto_restrict se contente de vérifier si la session est toujours valide.
Toute page comportant un appel à auto_restrict fait partie le la même session et reste protégée.

 
3  jerrywham le

Encore une petite appli bien pratique que je vais m'empresser de décortiquer. Merci.

 
4  jerrywham le

Bon je viens de commencer mon décorticage et je vois une toute chtite amélioration.
Ligne 33, tu utilises un @include pour éviter d'afficher une erreur si le fichier pass.php n'existe pas. Il serait beaucoup moins gourmand de tester la présence du fichier pour une inclusion éventuelle.

A place de @include('pass.php'), j'aurais donc mis if(file_exists('pass.php')) include('pass.php');

C'est un peu plus long à écrire mais beaucoup gourmand en terme de ressources.

Voilou. Je continue ma lecture...

 
5  Bronco le

Oui, en effet, le fait d'inhiber une erreur est très très gourmand en ressources.
A vrai dire, c'est une ligne victime du syndrome du "j'optimise ça plus tard" qui est restée là...
je corrige

 
6  jerrywham le

Petit retour d'expérience : ça marche nickel.

J'ai eu juste à réencoder le fichier en UTF-8 sans BOM car j'avais une erreur de header. A par ça nickel.

Je l'ai mis en place en deux coups de cuillère à pot sur le script shaarlo.

HS : une chtite remarque sur l'écriture du code. include étant une structure de langage et non une fonction (comme echo), il ne faut pas mettre de parenthèse. Tu peux directement écrire include 'auto_restrict.php';

 
7  Bronco le

Je l'ignorais... ça change quelque chose ?

 
8  jerrywham le

Non, c'est juste une question de bonnes pratiques...

 

Fil RSS des commentaires de cet article

✍ Écrire un commentaire

Inutile de poster un commentaire à la con pour vous faire de la pub, ce sera filtré et dégagé direct...

Quelle est la première lettre du mot etwx ?