Maison  >  Article  >  développement back-end  >  Solution d'implémentation de connexion unique version PHP

Solution d'implémentation de connexion unique version PHP

墨辰丷
墨辰丷original
2018-05-30 17:13:421646parcourir

Cet article présente principalement des exemples de solutions d'implémentation de connexion unique PHP. Il a une certaine valeur de référence. Si vous en avez besoin, vous pouvez en savoir plus.

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 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 implémenter 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 automatiquement ; déterminer 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 fonctionnement 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 + 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 la demande du webservice, 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. 本站登陆成功后,进行本地化的用户登陆处理,其后验证用户是否登陆只在本地验证。(本地存取登陆用户状态的信息,请设置为关闭浏览器就退出)

 3. 当检测用户登陆状态时,请先调用本地的验证处理,若本地验证不通过,再调用UClientSSO::checkUserLogin()方法到用户中心检测用户的登陆状态。

a) UClientSSO::checkUserLogin()方法如下:

 <?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. 单点登出时,调用UClientSSO::logoutSSO()方法。调用成功后,如需其他已登陆站立即登出,请调用 UClientSSO::getSynloginScript()方法获取W3C标准的script,在页面输出。

a) UClientSSO::logoutSSO()方法如下:        

<?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;
}
?>

四. 代码部署:         

1. 用户验证中心设置                 

a) 用户验证中心向分站提供的webservice服务接口文件,即UserSvc.php部署在hostname/webapps/port/ UserSvc.php中。查看wsdl内容,请访问https://hostname/port/ UserSvc.php?wsdl

 b) 用户中心用户单点服务类文件为UCenterSSO.class.php,文件路径为在hostname/webapps/include /UCenterSSO.class.php。该文件为用户单点登陆处理 的服务端类,被hostname/webapps/port/ UserSvc.php调用。用于获取用户的登陆信息,是否单点登陆的状态信息,单点登出处理等。

 c) 用户验证中心通过W3C标准,利用cookie方式记录,删除全站统一的用户唯一随机id 的脚本文件为hostname/webapps/port/cookie_mgr.php.

2. 子站点设置                 

a) 各子站点请将,UClientSSO.class.php部署在用户中心服务客户端目录下。部署好后,请修改最后一行的UClientSSO::setSite('1'); 参数值为用户验证中心统一分配给各站的标识id.

b) 在部署的用户中心服务客户端包下的api目录下下,请将logout_sso.php脚本转移到此处,并编写进行本站登出的处理脚本。

c) 在子站点验证用户登陆状态的代码部分,额外增加到用户中心的单点登陆验证的处理。

即在首先通过本站验证用户的登陆状态,如果未通过验证,则去用户中心验证。验证操作要调用UClientSSO::checkUserLogin();接口,接口含义请查看代码注释。

d) 在分站的登出处理脚本中,通过UClientSSO::getSynlogoutScript();获取script串输出即可。

五. 扩展功能:       

1. 记录跟踪所有在线用户

因为所有用户的登录都要经过用户验证中心,所有用户的ticket都在验证中心生成,可以将用户和该ticket(session id)在内存表中建立一个映射表。得到所有在线用户的记录表。

后期如有必要跟踪用户状态来实现其他功能,只要跟踪这个映射表就可以了。其他功能可以为: 获取在线用户列表,判断用户在线状态,获取在线用户人数等。

 2. 特殊统计处理

因为整个系统登录登出要经过用户验证中心,所以可以针对用户的特殊统计进行处理。如用户每天的登录次数,登陆时间,登陆状态失效时间,各时段的在线用户人数走势等。

六. 其他事项:       

1. 本站登陆状态有效时间问题:                  

全站要求用户登陆状态在关闭浏览器时就失效。要求各分站对session或cookie的处理方式按照如下进行:

a) Session方式记录用户登陆状态的站点

请在站点公用脚本开始处,添加一下代码

 <?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在浏览器未关闭时的持续存活时间   
 ?>

b) cookie方式记录用户登陆状态的站点

请在设置用户登陆状态的cookie时,设置cookie有效时间为null.

原文链接:http://www.cnblogs.com/linzhenjie/archive/2012/08/24/2653585.html

以上就是本文的全部内容,希望对大家的学习有所帮助。


相关推荐:

PHP数组分类、数组创建实例讲解

php pdo占位符的使用(代码实例讲解)

Explication détaillée du tableau de tri de tableaux multidimensionnels PHP

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

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