Subversion Repositories eFlore/Applications.del

Rev

Rev 2077 | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php
// declare(encoding='UTF-8');
/**
 * Classe de controle d'accès HTTP AUTH aux services de DEL, à n'utiliser
 * que dans ce cas (HTTP AUTH), et pas dans le cas de l'identification générale sur le SSO
 *
 * Cette classe propose des méthodes permettant :
 *  - l'authentification HTTP pour bloquer ou autoriser l'accès
 *  - de déterminer le statut d'admin des utilisateurs
 *
 * @category  DEL
 * @package   Services
 * @package   Bibliotheque
 * @version   0.1
 * @author    Mathias CHOUET <mathias@tela-botanica.org>
 * @author    Jean-Pascal MILCENT <jpm@tela-botanica.org>
 * @author    Aurelien PERONNET <aurelien@tela-botanica.org>
 * @license   GPL v3 <http://www.gnu.org/licenses/gpl.txt>
 * @license   CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
 * @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
 */
class ControleAcces {

        protected $conteneur;
        protected $bdd;

        public function __construct($conteneur) {
                $this->conteneur = $conteneur;
                $this->bdd = $this->conteneur->getBdd();
        }

        /**
         * Vérifie que l'IP du client est dans la liste "ip_autorisees" de la config
         * @throws Exception
         * @return boolean
         */
        public function controlerIpAutorisees() {
                $ipsAutorisees = $this->conteneur->getParametreTableau('ip_autorisees');

                $remoteIp = filter_input(INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP);
                $serverIp = filter_input(INPUT_SERVER, 'SERVER_ADDR', FILTER_VALIDATE_IP);
                if (in_array($remoteIp, $ipsAutorisees) == false) {
                        if ($remoteIp != $serverIp) {// ATTENTION : maintenir ce test à l'intérieur du précédent
                                $message = "Accès interdit. \n".
                                        "Vous n'êtes pas autorisé à accéder à ce service depuis '$remoteIp' !\n";
                                $code = RestServeur::HTTP_CODE_ACCES_NON_AUTORISE;
                                throw new Exception($message, $code);
                        }
                }
                return true;
        }

        /**
         * Exige qu'un administrateur s'autenthentifie à l'aide de HTTP AUTH
         */
        public function demanderAuthentificationAdmin() {
                if (!$this->etreAdminAutoriseParHttp()) {
                        $this->authentifierAdmin();
                }
        }

        /**
         * Exige qu'un utilisateur s'autenthentifie à l'aide de HTTP AUTH
         */
        public function demanderAuthentificationUtilisateur() {
                if (!$this->etreUtilisateurAutoriseParHttp()) {
                        $this->authentifierUtilisateur();
                }
        }

        /**
         * Lit les entêtes HTTP AUTH et vérifie si l'utilisateur
         * existe (courriel / mot de passe); si $doitEtreAdmin est true,
         * vérifiera également que l'utilisateur est administrateur de Del
         * 
         * @return boolean true si l'utilisateur est identifié, false sinon
         */
        protected function etreUtilisateurAutoriseParHttp($doitEtreAdmin=false) {
                $identifiant = $this->getAuthIdentifiant();
                $mdp = $this->getAuthMotDePasse();
                $existe = $this->obtenirUtilisateur($identifiant, $mdp);

                $autorisation = (isset($existe) && $existe) ? true :false; // c'est quoi ces tests de clodos ??

                if ($doitEtreAdmin === true) {
                        $autorisation = ($autorisation && $this->etreAdmin($identifiant));
                }
                return $autorisation;
        }

        /**
         * Lit les entêtes HTTP AUTH et vérifie que l'utilisateur est identifié
         * et est administrateur de Del
         * 
         * @return boolean true si l'utilisateur est identifié et admin de Del, false sinon
         */
        protected function etreAdminAutoriseParHttp() {
                return $this->etreUtilisateurAutoriseParHttp(true);
        }

        /**
         * Lit l'identifiant utilisateur dans les entêtes HTTP AUTH
         * @return String l'identifiant utilisateur ou null
         */
        protected function getAuthIdentifiant() {
                $id = (isset($_SERVER['PHP_AUTH_USER'])) ? $_SERVER['PHP_AUTH_USER'] : null;
                return $id;
        }

        /**
         * Lit le mot de passe dans les entêtes HTTP AUTH
         * @return String le mot de passe ou null
         */
        protected function getAuthMotDePasse() {
                $mdp = (isset($_SERVER['PHP_AUTH_PW'])) ? $_SERVER['PHP_AUTH_PW'] : null;
                return $mdp;
        }

        /**
         * Envoie un message HTTP 401 / une boîte de login HTTP AUTH avec des
         * messages correspondant à la demande d'authentification d'un administrateur
         * TODO: externaliser noms et adresses spécifiques à Tela Botanica
         * @return boolean
         */
        protected function authentifierAdmin() {
                $message_accueil = "Veuillez vous identifier avec votre compte administrateur Tela Botanica.";
                $message_echec = "Accès limité aux administrateurs de DEL.\n".
                        "Votre tentative d'identification a échoué.\n".
                        "Actualiser la page pour essayer à nouveau si vous êtes bien inscrit comme administrateur.";
                return $this->authentifier($message_accueil, $message_echec, 'Admin');
        }

        /**
         * Envoie un message HTTP 401 / une boîte de login HTTP AUTH avec des
         * messages correspondant à la demande d'authentification d'un utilisateur
         * TODO: externaliser noms et adresses spécifiques à Tela Botanica
         * @return boolean
         */
        protected function authentifierUtilisateur() {
                $message_accueil = "Veuillez vous identifier avec votre compte Tela Botanica.";
                $message_echec = "Accès limité aux utilisateurs de DEL.\n".
                        "Inscrivez vous http://www.tela-botanica.org/page:inscription pour le devenir.\n".
                        "Votre tentative d'identification a échoué.\n".
                        "Actualiser la page pour essayer à nouveau si vous êtes déjà inscrit ou contacter 'accueil@tela-botanica.org'.";
                return $this->authentifier($message_accueil, $message_echec, 'Utilisateur');
        }

        /**
         * Envoie l'authentification HTTP AUTH , et accepte un mode "debug" pour
         * les petits malins
         */
        protected function authentifier($message_accueil, $message_echec, $type) {
                $id = $this->getAuthIdentifiant();
                if (!isset($id)) {
                        $this->envoyerAuth($message_accueil, $message_echec);
                } else {
                        if ($type == 'Utilisateur' && $this->getAuthMotDePasse() == 'debug') {
                                $autorisation = true;
                        } else {
                                $methodeAutorisation = "etre{$type}Autorise";
                                $autorisation = $this->$methodeAutorisation();
                        }
                        if ($autorisation == false) {
                                $this->envoyerAuth($message_accueil, $message_echec);
                        }
                }
                return true;
        }

        /**
         * Envoie un message HTTP 401 / une boîte de login HTTP AUTH
         * @param string $message_accueil
         * @param string $message_echec
         */
        private function envoyerAuth($message_accueil, $message_echec) {
                header('HTTP/1.0 401 Unauthorized');
                header('WWW-Authenticate:  realm="'.mb_convert_encoding($message_accueil, 'ISO-8859-1', 'UTF-8').'"');
                header('Content-type: text/plain; charset=UTF-8');
                print $message_echec;
                exit(0);
        }

        /**
         * Authentifie et récupère un utilisateur directement depuis la table des
         * utilisateurs Del, utile pour l'authentification HTTP AUTH - ne pas
         * utiliser pour les services Del qui doivent être branchés au SSO
         */
        protected function obtenirUtilisateur($login, $motDePasse) {
                $login = $this->bdd->proteger($login);
                $motDePasse = $this->bdd->proteger($motDePasse);
                $requete = 'SELECT id_utilisateur, nom, prenom, courriel, mot_de_passe '.
                        'FROM del_utilisateur AS du '.
                        "WHERE courriel = $login ".
                        "       AND mot_de_passe = MD5($motDePasse) ".
                        ' -- '.__FILE__.':'.__LINE__."\n";
                $utilisateur = $this->bdd->recuperer($requete);
                return $utilisateur;
        }

        /**
         * Vérifie dans la table des utilisateurs Del qu'un utilisateur
         * (identifié par son courriel) est administrateur de Del
         * 
         * @param string $courriel
         * @return boolean true si l'utilisateur est administrateur de Del, false sinon
         */
        protected function etreAdmin($courriel) {
                $courriel = $this->bdd->proteger($courriel);
                $requete = 'SELECT dui.admin '.
                        'FROM del_utilisateur AS du LEFT JOIN del_user_infos AS dui ON (du.id_utilisateur = dui.id_utilisateur) '.
                        "WHERE du.courriel = $courriel ".
                        ' -- '.__FILE__.':'.__LINE__."\n";
                $infoUtilisateur = $this->bdd->recuperer($requete);
 
                $etreAdmin = $this->verifierDroitAdmin($infoUtilisateur['admin']);
                return $etreAdmin;
        }

        /**
         * Vérifie que la valeur "admin" d'un profil utilisateur correspond à la valeur
         * attendue dans la config
         * 
         * @return true si sébon, false si sépabon
         */
        protected function verifierDroitAdmin($droit) {
                $droitAdmin = $this->conteneur->getParametre('droit_superadmin');
                $etreAdmin = false;
                if (isset($droit) && $droit == $droitAdmin) {
                        $etreAdmin = true;
                }
                return $etreAdmin;
        }

}