Authentification des utilisateurs d'un site
#1
C'est une question qui revient souvent et que j'ai moi-même eu à résoudre: comment faire pour que les personnes inscrites sur un site soient automatiquement enregistrées sur les services IRC (anope).

La solution est assez simple, mais elle une (grosse) limite et quelques pré-requis:
Limite : vous ne pouvez lier qu'une seule base de données externe. Ceci est dû au module utilisé, mais j'ai bon espoir qu'il sera évolué pour permettre plusieurs connexions

Pré-requis :
  • un site avec une base de données (MySQL ou sqlite) utilisateurs dont vous connaissez l’algorithme de hashage du mot de passe
  • que cette base soit accessible à vos services
  • que les services incluent les modules m_mysql (ou m_sqlite) et m_sql_authentication

Base de données :
Dans mon exemple, les utilisateurs seront dans la table site_users qui contiendra les trois champs utiles: username, email et password (en MD5)

Configuration Anope :
Dans conf/modules.conf, il faut activer le module m_mysql (ou m_sqlite) et lui créer une connexion à la base de votre site. Si vous avez déjà une connexion (qui s'appelle souvent mysql/main), vous pouvez en créer une seconde.
Voici à quoi ressemble la configuration de ce module pour moi:

Code:
/*
* m_mysql [EXTRA]
*
* This module allows other modules to use MySQL.
*/
module
{
       name = "m_mysql"

       mysql
       {
               /* The name of this service. */
               name = "mysql/main"
               database = "db_anope"
               server = "127.0.0.1"
               username = "user"
               password = "password"
               port = 3306
       }

       mysql
       {
               name = "mysql/site"
               database = "db_site"
               server = "10.0.0.16"
               username = "site_user"
               password = "site_password"
               port = 3306
       }
}
La connexion mysql/main est celle qu'utilise anope par défaut (pour les stats par exemple), la connexion mysql/site sera utilisée pour la connexion des utilisateurs.

Ensuite, il suffit de configurer le module m_sql_authentification (toujours dans le même fichier):

Code:
/*
* m_sql_authentication [EXTRA]
*
* This module allows authenticating users against an external SQL database using a custom
* query.
*/
module
{
       name = "m_sql_authentication"

       /* SQL engine to use. Should be configured elsewhere with m_mysql, m_sqlite, etc. */
       engine = "mysql/site"

       /* Query to execute to authenticate. A non empty result from this query is considered a success,
        * and the user will be authenticated.
        *
        * @a@ is replaced with the user's account name
        * @p@ is replaced with the user's password
        * @n@ is replaced with the user's nickname
        * @i@ is replaced with the user's IP
        *
        * Note that @n@ and @i@ may not always exist in the case of a user identifying outside of the normal
        * nickserv/identify command, such as through the web panel.
        *
        * Furthermore, if a field named email is returned from this query the user's email is
        * set to its value.
        *
        *
        * We've included some example queries for some popular website/forum systems.
        *
        * Drupal 6: "SELECT `mail` AS `email` FROM `users` WHERE `name` = @a@ AND `pass` = MD5(@p@) AND `status` = 1"
        * e107 cms: "SELECT `user_email` AS `email` FROM `e107_user` WHERE `user_loginname` = @a@ AND `user_password` = MD5(@p@)"
        * SMF Forum: "SELECT `email_address` AS `email` FROM `smf_members` WHERE `member_name` = @a@ AND `passwd` = SHA1(CONCAT(LOWER(@a@), @p@))"
        * vBulletin: "SELECT `email` FROM `user` WHERE `username` = @a@ AND `password` = MD5(CONCAT(MD5(@p@), `salt`))"
        * IP.Board: "SELECT `email` FROM `ibf_members` WHERE `name` = @a@ AND `members_pass_hash` = MD5(CONCAT(MD5(`members_pass_salt`), MD5(@p@)))"
        */
       query = "SELECT `email` FROM site_users WHERE `username`= @a@ AND `user_password` = MD5(@p@)"

       /*
        * If set, the reason to give the users who try to "/msg NickServ REGISTER".
        * If not set, then registration is not blocked.
        */
       #disable_reason = "To register on this network visit http://some.misconfigured.site/register"

       /*
        * If set, the reason to give the users who try to "/msg NickServ SET EMAIL".
        * If not set, then email changing is not blocked.
        */
       #disable_email_reason = "To change your email address visit http://some.misconfigured.site"
}
Notez bien que la requête doit retourner un résultat sous la forme d'un seul champs pour authentifier un utilisateur (ça semble logique) mais que si ce champs s'appelle email, il mettra à jour l'email de l'utilisateur dans NickServ

Fonctionnement :
Lorsqu'un utilisateur envoie une commande d'identification sur IRC, Anope ira d'abord faire la requête du module. Deux options se présentent alors:
- La requête ne retourne pas de résultat => Anope va chercher dans sa propre base
- La requête retourne un résultat => Anope crée l'enregistrement dans sa base ou bien le met à jour (si jamais le mot de passe ou l'email ont changé)

Nota bene : Anope n'importe un utilisateur de la base du site que lorsqu'il tente de s'identifier, il appartiendra au propriétaire du site de créer un système qui fera une connexion et une authentification pour "réserver" le pseudo.

Danger : la base du site est prioritaire sur la base anope, c'est donc du côté du site qu'il faudra vérifier que la création d'un utilisateur n'écrase pas un utilisateur déjà existant.
zeolia: tchat gratuit, sans inscription ni publicité
Merci de ne pas demander d'aide en MP
Away
#2
Petit addendum: voici comment on peut faire une authentification irc avec du PHP:
PHP Code:
<?php
set_time_limit
(0);
$context stream_context_create([
    
'ssl' => [
        
'verify_peer' => false,
        
'verify_peer_name' => false
    
]
]);

$hostname 'tls://irc.zeolia.net:6697';
$socket stream_socket_client($hostname$errno$errstrini_get("default_socket_timeout"), STREAM_CLIENT_CONNECT$context);
if(!
$socket) {
    echo 
'Impossible de se connecter';
    exit;
}
fputs($socket,"USER PHPbot phpbot rasphost :Simple PHP bot\r\n");
fputs($socket,"NICK PHPbot\r\n");
$wait 1;
while(
$wait) {
    
$datas fgets($socket1024);
    
$cb explode(':',$datas);
    if(
rtrim($cb[0]) == 'PING')
    {
        
fputs($socket,'PONG :'.$cb[1]);
        
$wait 0;
    }
     if(
$datas)
        echo 
$datas;
}
fputs($socket,"PRIVMSG NickServ :IDENTIFY password\r\n");
fclose($socket); 

Faites bien attention à la commande USER (voir http://abcdrfc.free.fr/rfc-vf/rfc1459.html#413) qui doit prendre comme paramètres <nom d'utilisateur> <hôte> <nom de serveur> <nom réel>
zeolia: tchat gratuit, sans inscription ni publicité
Merci de ne pas demander d'aide en MP
Away
#3
Très bon tutoriel :)
#4
Merci pour cette perle :)


Forum Jump:


Users browsing this thread: 1 Guest(s)