Maison  >  Article  >  développement back-end  >  Exemple de solution d'implémentation d'authentification unique PHP

Exemple de solution d'implémentation d'authentification unique PHP

黄舟
黄舟original
2017-02-28 09:18:591358parcourir

Résumé :

Cet article présente principalement l'analyse et la conception d'un système d'authentification unique universel utilisant les technologies de service Web, de session et de cookies. Le langage d'implémentation spécifique est PHP. L'authentification unique, également connue sous le nom de Single Sign On en anglais, ou SSO en abrégé, constitue une partie importante du traitement complet des utilisateurs dans les entreprises et les activités de réseau actuelles. La définition du SSO est que dans plusieurs systèmes d'applications, les utilisateurs n'ont besoin de se connecter qu'une seule fois pour accéder à tous les systèmes d'applications mutuellement fiables.

Motivation :

Les amis qui ont utilisé la méthode de connexion sur le site complet d'ucenter doivent savoir qu'il s'agit d'une solution typique de modèle d'observateur. Le centre utilisateur est un sujet, et l'enregistrement et la suppression de ses observateurs sont unifiés dans le backend d'ucenter. Chaque site de sous-application correspond à un observateur. Chaque action de connexion dans le centre utilisateur déclenchera un script js pour rappeler l'interface de connexion du sous-site standard du w3c (api/uc.php).

Je pense que les inconvénients de cette méthode sont principalement deux points : 1. Lorsqu'il y a trop de sous-sites, l'interface de rappel augmentera en conséquence. Cela est dû à la limite du nombre de sous-sites distribués. . Comment le contrôler afin que l'efficacité de la connexion ne soit pas trop faible et difficile à comprendre ; 2. Lorsqu'un problème survient avec l'interface de rappel d'une certaine sous-station, le processus de connexion par défaut sera bloqué (le temps d'exécution du programme de connexion). peut être limité, mais s'il y a un problème correspondant, l'interface de rappel de la sous-station derrière la sous-station s'appellera Plus

Sur la base des problèmes ci-dessus, pendant le processus de développement actuel, j'ai conçu un autre panneau unique. -sur le système

1. Description du principe de connexion

Mécanisme technique de mise en œuvre de l'authentification unique : Lorsque l'utilisateur accède au système d'application 1 pour la première fois, car il ne s'est pas encore connecté, il sera dirigé vers le système d'authentification pour se connecter ; sur la base des informations de connexion fournies par l'utilisateur, le système d'authentification effectue une vérification d'identité, s'il réussit la validation, un identifiant d'authentification - le ticket doit être retourné à l'utilisateur ; lorsque l'utilisateur accède à d'autres applications, il apportera ce ticket avec lui comme son propre identifiant d'authentification. Une fois que le système d'application aura reçu la demande, il enverra le ticket au système d'authentification pour vérification et vérifiera la validité du ticket. . S'il réussit la vérification, l'utilisateur peut accéder au système d'application 2 et au système d'application 3 sans se reconnecter

On peut voir que pour mettre en œuvre le SSO, les fonctions principales suivantes sont requises :
a) Tous les systèmes d'application partagent un système d'authentification d'identité ;

b) Tous les systèmes d'application peuvent identifier et extraire les informations sur les tickets

c) Application Le système peut identifier les utilisateurs qui se sont connectés, et peut déterminer automatiquement si l'utilisateur actuel s'est connecté, complétant ainsi la fonction d'authentification unique

Sur la base des principes de base ci-dessus, j'ai conçu un ensemble de programmes système d'authentification unique en langage PHP, qui a maintenant été mis en service officiel du serveur de production. Ce programme système utilise les informations du ticket avec l'identifiant de session unique de l'ensemble du système comme moyen pour obtenir les informations complètes du site de l'utilisateur en ligne actuel (informations sur l'état de connexion et autres informations sur le site à l'échelle de l'utilisateur qui doivent être traitées).


2. Description du processus :
Processus de connexion :

1. Connectez-vous à un site pour la première fois :

a) L'utilisateur saisit le nom d'utilisateur et le mot de passe et envoie une demande de connexion au centre de vérification de l'utilisateur

b) Lors de la connexion actuelle au site, via une demande de service Web, le centre de vérification de l'utilisateur vérifie la légitimité du nom d'utilisateur et mot de passe. Si la vérification est réussie, un ticket est généré pour identifier l'utilisateur de la session en cours, et l'identifiant du site du sous-site actuellement connecté est enregistré dans le centre utilisateur. Enfin,

c) renvoie le. obtenu les données utilisateur et le ticket pour le stand du sous-site. Si la vérification échoue, le code d'état d'erreur correspondant est renvoyé.

d) Selon le résultat renvoyé par la requête du webservice à l'étape précédente, le sous-site actuel enregistre l'utilisateur : si le code d'état indique un succès, le site actuel enregistre le ticket via le cookie de ce site, et le site enregistre le statut de connexion de l'utilisateur. Si le code d'état indique un échec, l'utilisateur recevra une invite d'échec de connexion correspondante.

2. Une fois connecté, l'utilisateur accède à une autre sous-section :

a) Vérifiez le statut de connexion de l'utilisateur via le cookie ou la session du site : Si la vérification est réussie, entrez le normal programme de traitement du site ; Sinon, le centre utilisateur vérifie l'état de connexion de l'utilisateur (envoie un ticket au centre de vérification de l'utilisateur). Si la vérification est réussie, le traitement de connexion local est effectué sur les informations utilisateur renvoyées. pas connecté.


Processus de déconnexion
a) Le site de déconnexion actuel efface le statut de connexion de l'utilisateur sur le site et l'ID aléatoire unique de l'utilisateur enregistré localement sur l'ensemble du site

b) Via l'interface du service Web, effacez l'identifiant aléatoire unique enregistré sur l'ensemble du site. L'interface du service Web reviendra, déconnectera le code javascript des autres sous-sites connectés, et ce site affichera ce code.

c) Le code js accède au script de déconnexion standard W3C du site correspondant


3 Description du code :
Le code pertinent impliqué dans cet article. a été Package et téléchargement. Si vous êtes intéressé, vous pouvez cliquer pour télécharger sur le lien de téléchargement à la fin de cet article.

1. Processus de connexion :

À partir de l'ouverture du navigateur, le premier sous-site connecté doit appeler la méthode UClientSSO::loginSSO(). Cette méthode renvoie un identifiant aléatoire unique à l'ensemble du site et utilisé pour identifier l'utilisateur. Cet identifiant aléatoire a été enregistré via le cookie de ce site Web dans UClientSSO::loginSSO(), c'est-à-dire que le sous-site conserve le stub de l'identifiant de connexion de l'utilisateur sur ce site Web.

a) La méthode UClientSSO::loginSSO() est la suivante :


<?php
/**
 * 用户验证中心 登陆用户处理
 *
 * @param string $username   - 用户名
 * @param string $password   - 用户原始密码
 * @param boolean $remember   - 是否永久记住登陆账号
 * @param boolean $alreadyEnc  - 传入的密码是否已经经过simpleEncPass加密过
 *
 * @return array  - integer $return[&#39;status&#39;] 大于 0:返回用户 ID,表示用户登录成功
 *                        -1:用户不存在,或者被删除
 *                        -2:密码错
 *                                                 -11:验证码错误
 *                     string $return[&#39;username&#39;]   : 用户名
 *                     string $return[&#39;password&#39;]   : 密码
 *                     string $return[&#39;email&#39;]    : Email
 */

static public function loginSSO($username, $password, $remember=false, $alreadyEnc=false) {
self::_init();
self::_removeLocalSid();
$ret = array();

//
//1. 处理传入webservice接口的参数
//
$_params = array(
        &#39;username&#39; => $username,
        &#39;password&#39; => $alreadyEnc ? trim($password) : self::simpleEncPass(trim($password)),
        &#39;ip&#39;    => self::onlineip(),
        &#39;siteFlag&#39; => self::$site,
        &#39;remember&#39; => $remember
);
$_params[&#39;checksum&#39;] = self::_getCheckSum($_params[&#39;username&#39;] . $_params[&#39;password&#39;] .
$_params[&#39;ip&#39;] . $_params[&#39;siteFlag&#39;] . $_params[&#39;remember&#39;]);

//
// 2.调用webservice接口,进行登陆处理
//
$aRet = self::_callSoap(&#39;loginUCenter&#39;, $_params);

if (intval($aRet[&#39;resultFlag&#39;]) > 0 && $aRet[&#39;sessID&#39;]) {
//成功登陆
//设置本地session id
self::_setLocalSid($aRet[&#39;sessID&#39;]);

//设置用户中心的统一session id脚本路径
self::$_synloginScript = urldecode($aRet[&#39;script&#39;]);

$ret = $aRet[&#39;userinfo&#39;];
} else {

$ret[&#39;status&#39;] = $aRet[&#39;resultFlag&#39;];
}

return $ret;
}//end of function         

//b) 用户验证中心的webservice服务程序,接收到登陆验证请求后,调用UCenter::loginUCenter()方法来处理登陆请求。
/**
* 用户验证中心 登陆用户处理
*
* @param string $username
* @param string $password
* @param string $ip
* @param string $checksum
* @return array
*/
static public function loginUCenter($username, $password, $ip, $siteFlag, $remember=false) {
self::_init();
session_start();
$ret = array();
$arr_login_res   = login_user($username, $password, $ip);
$res_login     = $arr_login_res[&#39;status&#39;];        //
$ret[&#39;resultFlag&#39;] = $res_login;

if ($res_login < 1) {
//登陆失败
} else {

//登陆成功
$_SESSION[self::$_ucSessKey] = $arr_login_res;

$_SESSION[self::$_ucSessKey][&#39;salt&#39;] =
self::_getUserPassSalt($_SESSION[self::$_ucSessKey][&#39;username&#39;], $_SESSION[self::$_ucSessKey][&#39;password&#39;]);

$ret[&#39;userinfo&#39;] = $_SESSION[self::$_ucSessKey];
$ret[&#39;sessID&#39;]  = session_id();    //生成全站的唯一session id,作为ticket全站通行

//
//合作中心站回调登陆接口(设置用户中心的统一session id)
//
self::_createCoSitesInfo();
$uinfo = array();
$_timestamp = time();
$_rawCode = array(
            &#39;action&#39; => &#39;setSid&#39;,
            &#39;sid&#39;  => $ret[&#39;sessID&#39;],
            &#39;time&#39;  => $_timestamp,
);
if ($remember) {
$uinfo = array(
                &#39;remember&#39; => 1,
                &#39;username&#39; => $username,
                &#39;password&#39; => $password
);
}

$ret[&#39;script&#39;] = &#39;&#39;;
$_rawStr = http_build_query(array_merge($_rawCode, $uinfo));

//
// 合作站点的全域cookie设置脚本地址
//
foreach ((array)self::$_coSitesInfo as $_siteInfo) {
$_code = self::authcode($_rawStr, &#39;ENCODE&#39;, $_siteInfo[&#39;key&#39;]);
$_src = $_siteInfo[&#39;url&#39;] . &#39;?code=&#39; . $_code . &#39;&time=&#39; . $_timestamp;
$ret[&#39;script&#39;] .= urlencode(&#39;&#39;);
}

//
// 记住已登陆战
//
self::registerLoggedSite($siteFlag, $ret[&#39;sessID&#39;]);

unset($ret[&#39;userinfo&#39;][&#39;salt&#39;]);
}

return $ret;
}

?>



2. Une fois que le site Web s'est connecté avec succès, le traitement de connexion de l'utilisateur localisé est effectué et la vérification ultérieure pour savoir si l'utilisateur est connecté est effectuée uniquement localement. (Pour un accès local aux informations sur l'état de l'utilisateur connecté, veuillez le configurer pour qu'il se ferme après la fermeture du navigateur)

3. Lors de la détection de l'état de connexion de l'utilisateur, veuillez d'abord appeler le processus de vérification local si la vérification locale échoue. , rappelez-vous. La méthode UClientSSO::checkUserLogin() accède au centre utilisateur pour détecter l'état de connexion de l'utilisateur.

a) La méthode UClientSSO::checkUserLogin() est la suivante :

<?php
 /**
 * 用户单点登陆验证函数
 *
 * @return array  - integer $return[&#39;status&#39;] 大于 0:返回用户 ID,表示用户登录成功
 *                                                  0:用户没有在全站登陆
 *                        -1:用户不存在,或者被删除
 *                        -2:密码错
 *                        -3:未进行过单点登陆处理
 *                                                 -11:验证码错误
 *                     string $return[&#39;username&#39;]   : 用户名
 *                     string $return[&#39;password&#39;]   : 密码
 *                     string $return[&#39;email&#39;]    : Email
 */
 public static function checkUserLogin(){
 self::_init();
 $ret = array();
 $_sessId = self::_getLocalSid();
 if (empty($_sessId)) {
 //永久记住账号处理
 if(isset($_COOKIE[_UC_USER_COOKIE_NAME]) && !empty($_COOKIE[_UC_USER_COOKIE_NAME])) {
 
 //
 // 根据cookie里的用户名和密码判断用户是否已经登陆。
 //
 $_userinfo = explode(&#39;|g|&#39;, self::authcode($_COOKIE[_UC_USER_COOKIE_NAME], &#39;DECODE&#39;, self::$_authcodeKey));
 
 $username = $_userinfo[0];
 $password = isset($_userinfo[1]) ? $_userinfo[1] : &#39;&#39;;
 if (empty($password)) {
 $ret[&#39;status&#39;] = -3;
 } else {
 return self::loginSSO($username, $password, true, true);
 }
 
 } else {
 $ret[&#39;status&#39;] = -3;
 }
 
 } else {
 //
 //本站原先已经登陆过,通过保留的sesson id存根去用户中心验证
 //
 $_params = array(
             &#39;sessId&#39;  => $_sessId,
             &#39;siteFlag&#39; => self::$site,
             &#39;checksum&#39; => md5($_sessId . self::$site . self::$_mcComunicationKey)
 );
 $aRet = self::_callSoap(&#39;getOnlineUser&#39;, $_params);
 if (intval($aRet[&#39;resultFlag&#39;]) > 0) {
 //成功登陆
 $ret = $aRet[&#39;userinfo&#39;];
 } else {
 $ret[&#39;status&#39;] = $aRet[&#39;resultFlag&#39;];
 }
 }
 
 return $ret;
 }       
 
 b) 用户验证中心的webservice服务程序,接收到检验登陆的请求后,调用UCenter::getOnlineUser()方法来处理登陆请求:
 [php]/**
 * 根据sid,获取当前登陆的用户信息
 *
 * @param string $sessId    - 全站唯一session id,用做ticket
 * @return array
 */
 /**
 * 根据sid,获取当前登陆的用户信息
 *
 * @param string $sessId    - 全站唯一session id,用做ticket
 * @return array
 */
 static public function getOnlineUser($sessId, $siteFlag) {
 self::_init();
 session_id(trim($sessId));
 session_start();
 
 $ret = array();
 $_userinfo = $_SESSION[self::$_ucSessKey];
 
 if (isset($_userinfo[&#39;username&#39;]) && isset($_userinfo[&#39;password&#39;]) &&
 self::_getUserPassSalt($_userinfo[&#39;username&#39;], $_userinfo[&#39;password&#39;])) {
 $ret[&#39;resultFlag&#39;] = "1";
 $ret[&#39;userinfo&#39;] = $_userinfo;
 
 self::registerLoggedSite($siteFlag, $sessId);        //记住已登陆战
 unset($ret[&#39;userinfo&#39;][&#39;salt&#39;]);
 } else {
 $ret[&#39;resultFlag&#39;] = "0";
 }
 
 return ($ret);
 }
 ?>



4. Lors d'une déconnexion unique, appelez UClientSSO : méthode logoutSSO(). Une fois l'appel réussi, si vous souhaitez que les autres sites connectés se déconnectent immédiatement, veuillez appeler la méthode UClientSSO::getSynloginScript() pour obtenir le script standard du W3C et l'afficher sur la page.

a) La méthode UClientSSO::logoutSSO() est la suivante :

<?php
/**
* 全站单点登出
* - 通过webservice请求注销掉用户的全站唯一标识
*
* @return integer  1: 成功
*                   -11:验证码错误
*/
public static function logoutSSO(){
    self::_init();
    $_sessId = self::_getLocalSid();
    //
    //本站没有登陆的话,不让同步登出其他站
    //
    if (empty($_sessId)) {
        self::_initSess(true);
        return false;
    }
    $_params = array(
        &#39;sessId&#39;  => $_sessId,
        &#39;siteFlag&#39; => self::$site,
        &#39;checksum&#39; => md5($_sessId . self::$site . self::$_mcComunicationKey)
    );
    $aRet = self::_callSoap(&#39;logoutUCenter&#39;, $_params);
    if (intval($aRet[&#39;resultFlag&#39;]) > 0) {
        //成功登出
        self::_removeLocalSid();        //移除本站记录的sid存根
        self::$_synlogoutScript = urldecode($aRet[&#39;script&#39;]);
        $ret = 1;
    } else {
        $ret = $aRet[&#39;resultFlag&#39;];
    }
    return intval($ret);
}          [/php]
    b) 用户验证中心的webservice服务程序,接收到全站登出请求后,调用UCenter::loginUCenter()方法来处理登陆请求:
/**
* 登出全站处理
*
* @param string - 全站唯一session id,用做ticket
* @return boolean
*/
static public function logoutUCenter($sessId) {
    self::_init();
    session_id(trim($sessId));
    session_start();
    $_SESSION = array();
    return empty($_SESSION) ? true : false;
}
?>



IV. 🎜>
1. Paramètres du centre d'authentification des utilisateurs

a) Le fichier d'interface du service Web fourni par le centre d'authentification des utilisateurs à la sous-station, à savoir UserSvc.php, est déployé dans hostname/webapps. /port/ UserSvc.php. Pour afficher le contenu wsdl, veuillez visiter http://www.php.cn/ UserSvc.php?wsdl

b) Le fichier de classe de service à point unique de l'utilisateur du centre utilisateur est UCenterSSO.class.php, et le fichier le chemin est dans le nom d'hôte/webapps/include/UCenterSSO.class.php. Ce fichier est la classe de serveur pour le traitement de la connexion unique des utilisateurs et est appelé par hostname/webapps/port/UserSvc.php. Utilisé pour obtenir les informations de connexion de l'utilisateur, des informations d'état sur l'opportunité de se connecter en un seul point, un traitement de déconnexion unique, etc.

c) Le centre de vérification des utilisateurs respecte la norme W3C et utilise des cookies pour enregistrer et supprimer l'ID aléatoire unique de l'utilisateur dans l'ensemble du site. Le fichier de script est hostname/webapps/port/cookie_mgr.php.

2 Les paramètres du sous-site
A) S'il vous plaît, s'il vous plaît, uclientsso.class.php est déployé dans le répertoire client du service du centre utilisateur. Après le déploiement, veuillez modifier la dernière ligne de UClientSSO::setSite('1'); La valeur du paramètre est l'identifiant d'identification uniformément attribué à chaque site par le centre de vérification des utilisateurs

b) Servir le client dans le. centre utilisateur déployé Dans le répertoire api sous le package, veuillez transférer le script logout_sso.php ici et écrire un script de traitement pour vous déconnecter de ce site.

c) Dans la section de code permettant de vérifier le statut de connexion de l'utilisateur sur le sous-site, un traitement supplémentaire de vérification d'authentification unique dans le centre utilisateur est ajouté.

Autrement dit, vérifiez d'abord le statut de connexion de l'utilisateur via ce site. Si la vérification échoue, accédez au centre d'utilisateur pour vérification. L'opération de vérification nécessite l'appel de l'interface UClientSSO::checkUserLogin(); Veuillez consulter les commentaires du code pour connaître la signification de l'interface.

d) Dans le script de traitement de déconnexion de la station secondaire, utilisez UClientSSO::getSynlogoutScript();


5. Fonctions étendues :
1. Enregistrez et suivez tous les utilisateurs en ligne

Parce que toutes les connexions des utilisateurs doivent passer par le centre de vérification des utilisateurs, toutes utilisateurs Les tickets sont générés dans le centre de vérification, et une table de mappage peut être établie entre l'utilisateur et le ticket (identifiant de session) dans la table mémoire. Obtenez une liste d'enregistrement de tous les utilisateurs en ligne.

S'il est nécessaire de suivre le statut de l'utilisateur à l'avenir pour implémenter d'autres fonctions, suivez simplement ce tableau de mappage. D'autres fonctions peuvent être : l'obtention d'une liste d'utilisateurs en ligne, la détermination du statut en ligne de l'utilisateur, l'obtention du nombre d'utilisateurs en ligne, etc.

2. Traitement statistique spécial

Étant donné que l'ensemble de la connexion et de la déconnexion du système doit passer par le centre de vérification des utilisateurs, des statistiques spéciales des utilisateurs peuvent être traitées. Tels que le nombre de connexions d'utilisateurs par jour, l'heure de connexion, l'heure d'expiration du statut de connexion, la tendance du nombre d'utilisateurs en ligne au cours de chaque période, etc.


6. Autres questions :                                                                                                  L'état est perdu lorsque le navigateur est fermé. Chaque site de branche est tenu de gérer les sessions ou les cookies comme suit :
a) Sites qui enregistrent le statut de connexion des utilisateurs en mode Session

Veuillez ajouter le code suivant au début du script public du site

🎜 >





b) Sites qui utilisent des cookies pour enregistrer le statut de connexion des utilisateurs

Veuillez définir la période de validité des cookies sur null.

<?php
 session_write_close();
 ini_set(&#39;session.auto_start&#39;, 0);          //关闭session自动启动
 ini_set(&#39;session.cookie_lifetime&#39;, 0);      //设置session在浏览器关闭时失效
 ini_set(&#39;session.gc_maxlifetime&#39;, 3600); //session在浏览器未关闭时的持续存活时间   
 ?>

Ce qui précède est le contenu de l'exemple de la version PHP de la solution d'implémentation de connexion unique. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois (www.php.cn) !




-->

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn