Dotclear 2 stocke par défaut les utilisateurs et leurs mots de passe dans sa propre base de données. Le processus d'authentification passe donc tout naturellement par là. Ceci dit, il peut être utile d'accéder à une autre source de données pour procéder à l'authentification. Nous allons voir que Dotclear 2 le permet assez facilement.
Dotclear 2 permet de spécifier dans sa configuration un service définissant le nom de la classe qui sera utilisée pour le processus d'authentification.
Au même niveau que notre fichier de configuration, nous allons créer un fichier nommé MyAuth.php qui contiendra tout simplement le code suivant :
namespace Myself; use Dotclear\Core\Auth; class MyAuth extends Auth { }
Enfin, dans le fichier de configuration de Dotclear, nous ajoutons ces lignes à la fin :
Autoloader::me()->addNamespace('Myself', __DIR__); \Dotclear\Helper\Container\Factories::addService( 'core', Dotclear\Interface\Core\AuthInterface::class, Myself\MyAuth::class );
À partir de la version 2.32 de Dotclear il sera plus simple d'ajouter plutôt ces lignes (la 2e change) :
Autoloader::me()->addNamespace('Myself', __DIR__); define('DC_AUTH_CLASS', Myself\MyAuth::class);
À ce stade, notre installation de Dotclear doit continuer à fonctionner. Pour l'instant nous avons simplement changé la classe d'authentification et comme notre nouvelle classe ne fait rien, rien n'a changé.
Important :
La classe d'authentification doit impérativement hériter de Dotclear\Core\Auth pour être utilisée.Dans le cadre de ces explications, nous allons partir du principe que nous disposons d'un service web XML-RPC qui permet de vérifier la validité d'un identifiant et de son mot de passe et d'obtenir des informations sur l'utilisateur.
Voici les spécifications de notre service Web d'authentification fictif.
L'URL du service est http://example.com/auth et il possède une seule méthode auth.login.
Cette méthode prend deux paramètres : une chaîne login pour l'identifiant de l'utilisateur et une chaîne password pour le mot de passe. Elle renvoie un tableau contenant les informations sur l'utilisateur ou provoque une erreur XML-RPC en cas d'erreur d'identifiant et/ou de mot de passe.
Enfin, nous allons partir du principe que notre installation ne contient qu'un seul blog dont l'identifiant est default.
Dans le cadre de notre service d'authentification, nous devons nous intéresser à la méthode checkUser de Dotclear\Core\Auth puisque c'est là que tout se passe. Cette méthode est appelée de différente manière par Dotclear.
Elle peut être appelée avec uniquement l'identifiant de l'utilisateur. Ceci permet d'initialiser les informations dans la classe.
Elle peut être appelée avec l'identifiant et un mot de passe. Ceci permet de vérifier le mot de passe en plus d'initialiser l'utilisateur.
Enfin, elle peut être appelée avec un identifiant, un mot de passe de valeur null et une clé de vérification. Ceci permet de valider la session de l'utilisateur et de l'initialiser à l'aide d'une clé.
Voici comment nous allons procéder :
On notera que l'utilisateur doit exister dans la base de données pour des raisons d'intégrité référentielle. En effet, il est nécessaire de pouvoir associer des billets (entre autre) à tel ou tel utilisateur.
Il est également nécessaire de stocker le mot de passe de l'utilisateur dans la base de données de Dotclear car certaines opérations en ont besoin. Ceci étant, il est possible d'interdire le changement de mot de passe par l'utilisateur.
Voici donc maintenant le code commenté de notre nouvelle classe d'authentification :
namespace Myself; class MyAuth extends Dotclear\Core\Auth { # L'utilisateur n'a pas le droit de changer son mot de passe protected $allow_pass_change = false; # La méthode de vérification du mot de passe public function checkUser($user_id, $pwd=null, $user_key=null) { # Pas de mot de passe, on appelle la méthode parente. if ($pwd == '') { return parent::checkUser($user_id,null,$user_key); } # Si un mot de passe a été donné, nous allons le vérifier avec la # méthode auth.login XML-RPC. try { # On démarre une transaction et on ouvre un curseur sur la # table utilisateur de Dotclear pour créer ou modifier # l'utilisateur. $this->con->begin(); $cur = $this->con->openCursor($this->user_table); # On appelle la méthode de vérification du mot de passe. # En cas d'erreur le processus s'arrête là et provoque # une exception. $client = new xmlrpcClient('http://example.com/auth'); $info = $client->query('auth.login',$user_id,$pwd); # On définit le mot de passe, il est inséré dans tous les cas. $cur->user_pwd = $pwd; # Si l'utilisateur existe, nous allons uniquement mettre à jour # son mot de passe dans la table utilisateur de Dotclear. if ($this->core->userExists($user_id)) { $this->sudo(array($this->core,'updUser'),$user_id,$cur); $this->con->commit(); } # Si l'utilisateur n'existe pas, nous allons le créer. # Afin qu'il puisse se connecter, il est nécessaire de lui donner # au moins une permission "usage" sur le blog "default". else { $cur->user_id = $info['login']; $cur->user_email = $info['email']; $cur->user_name = $info['name']; $cur->user_firstname = $info['firstname']; $cur->user_lang = $info['lang'] ? $info['lang'] : 'en'; $cur->user_tz = 'Europe/Paris'; $cur->user_default_blog = 'default'; $this->sudo(array($this->core,'addUser'),$cur); $this->sudo(array($this->core,'setUserBlogPermissions'), $user_id,'default',array('usage'=>true)); $this->con->commit(); } # Les opérations précédentes se sont déroulées sans erreur, nous # pouvons maintenant appeler la méthode parente afin d'initialiser # l'utilisateur dans l'object $core->auth return parent::checkUser($user_id,$pwd); } catch (Exception $e) { # En cas d'erreur on annule la transaction et on renvoie "false" $this->con->rollback(); return false; } } }
Note :
On notera l'utilisation de la propriété allow_pass_change qui permet d'interdire le changement de mot de passe par l'utilisateur.Comme on peut le voir, le processus est assez simple à mettre en place. Quelques remarques maintenant.
Cet exemple simple d'authentification montre ce qu'il est possible de faire. Vous pouvez ainsi authentifier un utilisateur depuis n'importe quelle source telle qu'un serveur LDAP, la table utilisateur d'un forum, ou n'importe quoi acceptant un identifiant et un mot de passe.
Enfin, la class Auth permet de réaliser une véritable authentification unique de type SSO par ces fonctions de vérification de session et de changement du formulaire d'authentification.