Heim  >  Artikel  >  Backend-Entwicklung  >  Single-Sign-In-Implementierungslösung für die PHP-Version

Single-Sign-In-Implementierungslösung für die PHP-Version

墨辰丷
墨辰丷Original
2018-05-30 17:13:421704Durchsuche

In diesem Artikel werden hauptsächlich Beispiele für PHP-Single-Sign-In-Implementierungslösungen vorgestellt. Bei Bedarf können Sie mehr darüber erfahren.

Zusammenfassung:

In diesem Artikel werden hauptsächlich die Analyse und das Design eines universellen Single-Sign-On-Systems unter Verwendung von Webservice-, Sitzungs- und Cookie-Technologien vorgestellt. Die spezifische Implementierungssprache ist PHP. Single Sign-On, im Englischen auch Single Sign On oder kurz SSO genannt, ist ein wichtiger Bestandteil der umfassenden Benutzerverarbeitung in aktuellen Unternehmen und Netzwerkunternehmen. Die Definition von SSO besteht darin, dass sich Benutzer in mehreren Anwendungssystemen nur einmal anmelden müssen, um auf alle gegenseitig vertrauenswürdigen Anwendungssysteme zuzugreifen.

Motivation:

Freunde, die die vollständige Anmeldemethode von ucenter verwendet haben, sollten wissen, dass dies eine typische Beobachtermusterlösung ist. Das User Center ist ein Subjekt, und die Registrierung und Löschung seiner Beobachter erfolgt einheitlich im Backend von ucenter. Jede Unteranwendungsstelle entspricht einem Beobachter. Jede Anmeldeaktion im Benutzercenter löst ein JS-Skript aus, um die W3C-Standard-Subsite-Anmeldeschnittstelle (api/uc.php) zurückzurufen.

Ich denke, die Nachteile dieser Methode liegen hauptsächlich in zwei Punkten: 1. Wenn zu viele Unterseiten vorhanden sind, erhöht sich die Rückrufschnittstelle entsprechend. Dies liegt an der Begrenzung der Anzahl verteilter Unterseiten . So steuern Sie es, damit die Anmeldeeffizienz nicht zu niedrig und schwer zu erfassen ist. 2. Wenn ein Problem mit der Rückrufschnittstelle einer bestimmten Unterstation auftritt, bleibt der Standard-Anmeldevorgang hängen (die Ausführungszeit des Anmeldeprogramms). kann eingeschränkt werden, aber wenn ein entsprechendes Problem vorliegt, wird die Rückrufschnittstelle der Unterstation hinter der Unterstation aufgerufen Nicht mehr

Aufgrund der oben genannten Probleme habe ich während des eigentlichen Entwicklungsprozesses ein weiteres einzelnes Schild entworfen -on-System

1. Beschreibung des Anmeldeprinzips

Technischer Implementierungsmechanismus des Single Sign-On: Wenn der Benutzer zum ersten Mal auf das Anwendungssystem 1 zugreift, weil er Wenn er sich noch nicht angemeldet hat, wird er zum Anmelden an das Authentifizierungssystem weitergeleitet. Basierend auf den vom Benutzer bereitgestellten Anmeldeinformationen führt das Authentifizierungssystem eine Identitätsüberprüfung durch. Wenn es die Validierung besteht, sollte ein Authentifizierungsnachweis zurückgegeben werden Wenn der Benutzer auf andere Anwendungen zugreift, wird er dieses Ticket als seinen eigenen Authentifizierungsnachweis mitbringen. Nachdem das Anwendungssystem die Anfrage erhalten hat, wird es zur Überprüfung an das Authentifizierungssystem weitergeleitet Wenn die Überprüfung bestanden wird, kann der Benutzer auf Anwendungssystem 2 und Anwendungssystem 3 zugreifen, ohne sich erneut anzumelden.

Es ist ersichtlich, dass zur Implementierung von SSO die folgenden Hauptfunktionen erforderlich sind:

a ) Alle Anwendungssysteme verfügen über ein gemeinsames Identitätsauthentifizierungssystem.

b) Alle Anwendungssysteme können Ticketinformationen identifizieren und extrahieren.

c) Die Anwendung kann automatisch angemeldete Benutzer identifizieren Stellen Sie fest, ob sich der aktuelle Benutzer angemeldet hat, und vervollständigen Sie damit die Single-Sign-On-Funktion.

Basierend auf den oben genannten Grundprinzipien habe ich eine Reihe von Single-Sign-On-Systemprogrammen in PHP-Sprache entworfen, die jetzt implementiert wurden offizieller Produktionsserverbetrieb. Dieses Systemprogramm verwendet die Ticketinformationen mit der eindeutigen Sitzungs-ID des gesamten Systems als Medium, um die gesamten Site-Informationen des aktuellen Online-Benutzers (Anmeldestatusinformationen und andere benutzerweite Site-Informationen, die verarbeitet werden müssen) abzurufen.

2. Prozessbeschreibung:

Anmeldevorgang:

1. Melden Sie sich zum ersten Mal auf einer Website an:

a) Der Benutzer gibt den Benutzernamen + das Passwort ein und sendet eine Anmeldeanfrage an das Benutzerverifizierungszentrum

b) Wenn er sich gerade auf der Website anmeldet, überprüft das Benutzerverifizierungszentrum über die Webservice-Anfrage die Legitimität des Benutzernamens und Passwort. Wenn die Überprüfung bestanden wird, wird ein Ticket generiert, um den Benutzer der aktuellen Sitzung zu identifizieren, und die Site-ID der aktuell angemeldeten Unterseite wird im Benutzercenter aufgezeichnet. Abschließend wird

c) zurückgegeben erhaltene Benutzerdaten und Eintrittskarte zur Unterseite. Wenn die Überprüfung fehlschlägt, wird der entsprechende Fehlerstatuscode zurückgegeben.

d) Gemäß dem von der Webservice-Anfrage im vorherigen Schritt zurückgegebenen Ergebnis meldet die aktuelle Unterseite den Benutzer an: Wenn der Statuscode Erfolg anzeigt, speichert die aktuelle Seite das Ticket über das Cookie davon Die Site zeichnet den Anmeldestatus des Benutzers auf. Wenn der Statuscode einen Fehler anzeigt, erhält der Benutzer eine entsprechende Meldung zum Anmeldefehler.

2. Wenn der Benutzer angemeldet ist, geht er zu einem anderen Unterabschnitt:

a) Überprüfen Sie den Anmeldestatus des Benutzers über das Cookie oder die Sitzung der Website: Wenn die Überprüfung bestanden wurde, geben Sie den Normalen ein Andernfalls überprüft das Benutzercenter den Anmeldestatus des Benutzers (sendet ein Ticket an das Benutzerüberprüfungscenter. Wenn die Überprüfung erfolgreich ist, wird die lokale Anmeldeverarbeitung für die zurückgegebenen Benutzerinformationen durchgeführt.) nicht eingeloggt.

Abmeldevorgang

a) Die aktuelle Abmeldeseite löscht den Anmeldestatus des Benutzers für die Site und die eindeutige Zufalls-ID des lokal gespeicherten Benutzers für die gesamte Site

b) Löschen Sie über die Webservice-Schnittstelle die eindeutige Zufalls-ID, die auf der gesamten Site aufgezeichnet wurde. Die Webservice-Schnittstelle kehrt zurück, meldet den Javascript-Code anderer angemeldeter Unterseiten ab und diese Site gibt diesen Code aus.

c) js-Code greift auf das W3C-Standard-Abmeldeskript der entsprechenden Site zu

3. Codebeschreibung:

Der relevante Code, der in diesem Artikel enthalten ist Wenn Sie interessiert sind, können Sie auf den Download-Link am Ende dieses Artikels klicken.

1. Anmeldevorgang:

Ab dem Öffnen des Browsers muss die erste angemeldete Unterseite die Methode UClientSSO::loginSSO() aufrufen. Diese Methode gibt eine zufällige ID zurück, die für die gesamte Site eindeutig ist und zur Identifizierung des Benutzers verwendet wird. Diese zufällige ID wurde durch das Cookie dieser Website in UClientSSO::loginSSO() gespeichert, d. h. die Unterseite behält den Stub der Login-ID des Benutzers auf dieser Website.

a) Die UClientSSO::loginSSO()-Methode lautet wie folgt:

 <?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占位符的使用(代码实例讲解)

Detaillierte Erläuterung des mehrdimensionalen PHP-Array-Sortierarrays

Das obige ist der detaillierte Inhalt vonSingle-Sign-In-Implementierungslösung für die PHP-Version. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn