Système de login sécurisé – CMS CodeIgniter, partie 2

Dans mon article précédent, on a vu comment installer et configurer le framework PHP CodeIgniter. Aujourd’hui, on commence le développement de notre moteur de site Web. Au programme, la base de données et le système de login sécurisé.

Avant de commencer

Cet article est le second d’un ensemble d’article sur la création d’un système de gestion de contenu en utilisant le framework PHP CodeIgniter. Je vous invite donc à lire le précédent article pour partir sur de bonnes bases et avoir une installation saine de CodeIgniter pour l’article actuel.

Okay, on a donc convenu mercredi que l’on partira sur un simple CMS pour l’instant, donc ici pas de gestion de catalogue produit, pas de blog, juste un gestionnaire de pages (bien qu’intégrer un blog ne soit pas franchement différent de ce dernier). Allez, on se lance!

Création de la base de données

Comme notre CMS sera très simple, on aura pas beaucoup de tables dans notre base de données, et quand je dis pas beaucoup, c’est déjà trop. On aura donc une table users qui nous permettra d’enregistrer les infos de connexion des différents utilisateurs de notre CMS. Ici rien de très compliqué:

CREATE TABLE users (
  id int NOT NULL AUTO_INCREMENT,
  username varchar(50) UNIQUE NOT NULL,
  password varchar(255) NOT NULL,
  PRIMARY KEY (id)
);

On a donc ici un champ username qui devra être unique, un champ password pour le mot de passe que l’on cryptera en SHA1, je n’aime pas trop MD5 même si ça peut faire l’affaire ici.

Ensuite, la dernière table de notre base sera une table dans laquelle on enregistrera le contenu des pages présentent sur le site. La encore rien de compliqué, j’ai même choisi de disposé de champs afin de renseigner les balises meta pour l’indexation des pages dans Google (un peu de SEO ne fait pas de mal).

CREATE TABLE pages (
  id int NOT NULL AUTO_INCREMENT,
  title varchar(100) NOT NULL,
  content longtext NOT NULL,
  keywords text NOT NULL,
  description text NOT NULL,
  PRIMARY KEY (id)
);

J’ai vraiment besoin d’expliquer?

Okay, on va maintenant créer le fichier qui permettra de récupérer les données présentes dans la base de données.

Création du Modèle Users_model.php

Qu’est-ce que ça veut bien dire? Vous vous rappelez dans le précédent article on a parlé de Modèle MVC, et bien Users_model.php c’est le ‘M’ de ‘MVC’. C’est ici qu’on va écrire nos fonctions « CRUD » (Create, Read, Update, Delete), on utilisera ensuite ces fonction dans notre Contrôleur, qui traitera les données retournées par notre Modèle, et les affichera dans la Vue.

Allez on se lance, ce sera plus clair quand on aura mit les pieds dans le code. Donc, dans le dossier application/models on créé le fichier u_sers_model.php_ qui contiendra ceci :

<?php
class User_model extends Model {
     function User_model(){
          parent::Model();
     }
}
?>

Ici on créé la classe User_model qui hérite de la classe Model, puis on instancie la classe avec le constructeur User_model (on aurai pu aussi utiliser __constructor pour l’instancier).

On va maintenant créer notre fonction qui vérifiera les infos de login passées au formulaire qu’on verra plus tard. Dans la classe User_model, sous notre constructeur du même nom, ajoutez la fonction suivante :

function validCredentials($username,$password){
     $this->load->library('encrypt');

     $password = $this->encrypt->sha1($password);

     //requête préparée, beaucoup plus sécurisé
     $q = "SELECT * FROM users WHERE username = ? AND password = ?";

     $data = array($username,$password);
     $q = $this->db->query($q,$data);

     if($q->num_rows() > 0){
          $r = $q->result();
          $session_data = array('username' => $r[0]->username,'logged_in' => true);
          $this->session->set_userdata($session_data);
          return true;
     } else { return false; }
}

Que ce passe-t-il ici?

D’abord on charge la librairie encrypt avec la commande $this->load->library('encrypt') ce qui nous permet d’utiliser les fonctions de cette librairie dans notre modèle. Ensuite on crypte en SHA1 le mot de passe passé en paramètre à la fonction. Enfin, on exécute la requête stockée dans la variable $q avec $this->db->query() en lui passant le tableau $data pour remplacer les points d’interrogation dans notre requête ; c’est une requête préparée, j’en avais parlé l’an dernier dans un article sur l’Objet PDO.

Si la requête nous renvoi un résultat, on créé deux variable de sessions username et logged_in qui permettra de savoir si on a accès ou non à notre admin. Sinon validCredentials nous retourne false.

On va ajouter aussi une autre fonction pour savoir si on est bien loggué. On pourrait s’en passer mais ça nous évitera quelques lignes de code dans notre contrôleur. Celle ci est simple, ajoutez la fonction suivante à l’intérieur de votre Modèle:

function isLoggedIn(){
     if($this->session->userdata('logged_in'))
     { return true; } else { return false; }
}

Il reste encore du monde? On passe au Contrôleur

Maintenant qu’on a notre Modèle pour l’accès à la base de données, il est temps de les manipuler ces petites données! Créez un fichier  admin.php dans le dossier a_pplication/controllers_ et mettez y le code suivant:

class Admin extends Controller {

     //constructeur de la classe
     function Admin() {
          parent::Controller();
          $this->load->model('user_model');
     }
}

Ici comme notre avec notre User_model, on crée une classe Admin qui hérite de la classe Controller, et on l’initialise grace à son constructeur, dans lequel on charger notre modèle User_model, ce qui nous permettra d’utiliser ses fonctions dans notre contrôleur Admin.

Maintenant que notre contrôleur est instancié, on va ajouter les fonctions (ou méthodes) qui nous permettrons d’envoyer les données du formulaire de login à notre Modèle et ainsi définir si on a accès ou non à notre backoffice.

La première fonction qu’on va inclure dans notre classe Admin, et la fonction index() qui nous servira de page d’accueil. En gros lorsqu’on accédera à l’adresse http://localhost:8888/cms/index.php/admin, c’est notre fonction iindex() qui sera appelée.

function index(){
     if($this->user_model->isLoggedIn()){
          redirect('admin/dashboard','refresh');
     } else {
          redirect('admin/login','refresh');
     }
}

Ici on vérifie si on est bien loggué, dans ce cas on redirige à l’adresse http://localhost:8888/index.php/admin/dashboard qui est le tableau de bord de notre CMS, sinon on redirige au formulaire de login.

Parlons du formulaire de login. Pour traiter les données soumises au formulaire, on va créer une méthode login() dans notre contrôleur.

function login(){
     if($this->user_model->isLoggedIn()){
          redirect('admin','refresh');
     } else {
          //on charge la validation de formulaires
          $this->load->library('form_validation');

          //on définit les règles de succès
          $this->form_validation->set_rules('username','Login','required');
          $this->form_validation->set_rules('password','Mot de passe','required');

          //si la validation a échouée on redirige vers le formulaire de login
          if(!$this->form_validation->run()){
               $this->load->view('loginform');
          } else {
               $username = $this->input->post('username');
               $password = $this->input->post('password');
               $validCredentials = $this->user_model->validCredentials($username,$password);

               if($validCredentials){
                    redirect('admin/dashboard','refresh');
               } else {
                    $data['error_credentials'] = 'Wrong Username/Password';
                    $this->load->view('loginform',$data);
               }
          }
     }
}

Ici on vérifie d’abord si on est loggué, dans ce cas on redirige vers l’admin, sinon on traite le formulaire. On charge la librairie form_validation, qui va nous permettre d’accéder à des fonctions de validation de champs déjà toute prête, notamment la fonction set_rules qui nous permettra de définir quels champs sont obligatoire, quel type de données accepter, etc. Lorsque nos règles d’acceptation sont validées, on vérifie que les login/mot de passe passés en paramètres retournent un résultant dans la base de données, via notre fonction validCredentials() qu’on a définit dans notre modèle User_model. Si un résultat est retourné, la fonction validCredentials créée la variable de session logged_in et nous redirige vers le dashboard.

Dernière méthode de notre contrôleur, la fonction dashboard() qui se chargera d’afficher notre tableau de bord.

function dashboard(){
     if($this->user_model->isLoggedIn())
          $this->load->view('admin');
}

Passons maintenant à nos deux « vues », loginform et admin. Ce sont les deux fichiers que l’on appelle avec la fonction $this->load->view() dans notre contrôleur. Dans le dossier application/views créez les fichier loginform.php et admin.php. La vue admin n’ayant pas trop d’intérêt pour l’instant, on va juste voir la vue loginform, qui nous permettra de voir comment créer facilement un formulaire avec CodeIgniter.

<?php
echo form_open('admin/login');
     echo form_label('Login','username');
     echo form_input('username',set_value('username'));

     echo form_label('Mot de passe','password');
     echo form_password('password');

     echo form_submit('submit','Connexion');
echo form_close();
echo validation_errors();
echo @$error_credentials;
?>

Ici on ouvre un tag <form> qui enverra le formulaire à la méthode login() du contrôleur Admin. Puis on affiche les erreurs de validation si il y a lieu avec la fonction validation_errors() et les erreurs de login/mot de passe avec notre variable $error_credentials.

Eh voilà, votre formulaire de login sécurisé est terminé!

Conclusion

Ici on a vue comment bien utiliser l’architecture trois tiers qui permet de séparer la couche présentation (nos Views), de la couche métier (notre Controller) et de la couche réseau (notre Model). Ainsi, si l’on veut changer de système de gestion de base de données et passer sur une base Oracle plutôt que MySQL, nous n’aurons qu’a changer les méthodes écrient dans notre modèle User_model.

Dans le prochain article, on s’attardera sur LE coeur de notre système, à savoir la gestion des pages. Allez, bon week-end!


Commentaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.