国产精品成人VA在线观看,亚洲日韩在线中文字幕综合,亚洲AV电影天堂男人的天堂,久久人人爽人人爽人人av东京热

News新聞

業(yè)界新聞動態(tài)、技術(shù)前沿
Who are we?

您的位置:首頁      樂道系統(tǒng)FAQ      PHP版單點登陸實現(xiàn)方案的實例

PHP版單點登陸實現(xiàn)方案的實例

標簽: 發(fā)布日期:2016-11-17 00:00:00 264

摘要:

本文主要介紹了利用webservice,session,cookie技術(shù),來進行通用的單點登錄系統(tǒng)的分析與設(shè)計。具體實現(xiàn)語言為PHP。單點 登錄,英文名為Single Sign On,簡稱為 SSO,是目前企業(yè),網(wǎng)絡(luò)業(yè)務(wù)的用戶綜合處理的重要組成部分。而SSO的定義,是在多個應(yīng)用系統(tǒng)中,用戶只需要登陸一次就可以訪問所有相互信任的應(yīng)用系 統(tǒng)。

動機:

用過ucenter的全站登錄方式的朋友,應(yīng)該都知道這是典型的觀察者模式的解決方案。用戶中心作為subject, 其所屬observer的注冊和刪除統(tǒng)一在ucenter的后臺進行。而各個子應(yīng)用站點都對應(yīng)一個observer。每次用戶中心的登錄動作,都會觸發(fā) js腳本回調(diào)w3c標準的子站登錄接口(api/uc.php)。

這種方式的缺點,本人認為主要是兩點:1. 子站點過多時,回調(diào)接口相應(yīng)增多,這個在分布子站的量的限制上,如何控制來使登錄效率不會太低,不好把握; 2. 當某個子站回調(diào)接口出現(xiàn)問題時,默認的登錄過程會卡住(可以限制登錄程序的執(zhí)行時間,但相應(yīng)出現(xiàn)問題子站后面的子站的回調(diào)接口就調(diào)不到了。

基于以上問題,在實際開發(fā)過程中,本人設(shè)計了另一套單點登錄系統(tǒng)。

一. 登陸原理說明

單點登錄的技術(shù)實現(xiàn)機制:當用戶第一次訪問應(yīng)用系統(tǒng)1的時候,因為還沒有登錄,會被引導(dǎo)到認證系統(tǒng)中進行登錄;根據(jù)用戶提供的登錄信息,認證系統(tǒng)進行身份效驗,如果通過效驗,應(yīng)該返回給用戶一個認證的憑據(jù)--ticket;用戶再訪問別的應(yīng)用的時候,就會將這個ticket帶上,作為自己認證的憑據(jù),應(yīng)用系統(tǒng)接受到請求之后會把ticket送到認證系統(tǒng)進行效驗,檢查ticket的合法性。如果通過效驗,用戶就可以在不用再次登錄的情況下訪問應(yīng)用系統(tǒng)2和應(yīng)用系統(tǒng)3了。

可以看出,要實現(xiàn)SSO,需要以下主要的功能:

a) 所有應(yīng)用系統(tǒng)共享一個身份認證系統(tǒng);

b) 所有應(yīng)用系統(tǒng)能夠識別和提取ticket信息;

c) 應(yīng)用系統(tǒng)能夠識別已經(jīng)登錄過的用戶,能自動判斷當前用戶是否登錄過,從而完成單點登錄的功能

基于以上基本原則,本人用php語言設(shè)計了一套單點登錄系統(tǒng)的程序,目前已投入正式生成服務(wù)器運行。本系統(tǒng)程序,將ticket信息以全系統(tǒng)唯一的 session id作為媒介,從而獲取當前在線用戶的全站信息(登陸狀態(tài)信息及其他需要處理的用戶全站信息)。

二. 過程說明:

登陸流程:

1. 第一次登陸某個站:

a) 用戶輸入用戶名+密碼,向用戶驗證中心發(fā)送登錄請求

b) 當前登錄站點,通過webservice請求,用戶驗證中心驗證用戶名,密碼的合法性。如果驗證通過,則生成ticket,用于標識當前會話的用戶,并將當前登陸子站的站點標識符記錄到用戶中心,最后

c) 將獲取的用戶數(shù)據(jù)和ticket返回給子站。如果驗證不通過,則返回相應(yīng)的錯誤狀態(tài)碼。

d) 根據(jù)上一步的webservice請求返回的結(jié)果,當前子站對用戶進行登陸處理:如狀態(tài)碼表示成功的話,則當前站點通過本站cookie保存ticket,并本站記錄用戶的登錄狀態(tài)。狀態(tài)碼表示失敗的話,則給用戶相應(yīng)的登錄失敗提示。

2. 登陸狀態(tài)下,用戶轉(zhuǎn)到另一子:

a) 通過本站cookie或session驗證用戶的登錄狀態(tài):如驗證通過,進入正常本站處理程序;否則戶中心驗證用戶的登錄狀態(tài)(發(fā)送ticket到用戶驗證中心),如驗證通過,則對返回的用戶信息進行本地的登錄處理,否則表明用戶未登錄。

登出流程

a) 當前登出站清除用戶本站的登錄狀態(tài) 和 本地保存的用戶全站唯一的隨機id

b) 通過webservice接口,清除全站記錄的全站唯一的隨機id。webservice接口會返回,登出其他已登錄子站的javascript代碼,本站輸出此代碼。

c) js代碼訪問相應(yīng)站W(wǎng)3C標準的登出腳本

三. 代碼說明:

本文所涉及到相關(guān)代碼,已打包上傳,如有興趣,可在本文最后下載鏈接處點擊下載。

1. 登陸流程:

用戶從打開瀏覽器開始,第一個登陸的子站點,必須調(diào)用UClientSSO::loginSSO()方法。該方法返回全站唯一的隨機id用于標識該用戶。該隨機id在UClientSSO::loginSSO()中已通過本站cookie保存,即該子站點保留了用戶已登陸標識的存根于本站。

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

 <?php
/**
 * 用戶驗證中心 登陸用戶處理
 *
 * @param string $username   - 用戶名
 * @param string $password   - 用戶原始密碼
 * @param boolean $remember   - 是否永久記住登陸賬號
 * @param boolean $alreadyEnc  - 傳入的密碼是否已經(jīng)經(jīng)過simpleEncPass加密過
 *
 * @return array  - integer $return['status'] 大于 0:返回用戶 ID,表示用戶登錄成功
 *                        -1:用戶不存在,或者被刪除
 *                        -2:密碼錯
 *                                                 -11:驗證碼錯誤
 *                     string $return['username']   : 用戶名
 *                     string $return['password']   : 密碼
 *                     string $return['email']    : Email
 */

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

//
//1. 處理傳入webservice接口的參數(shù)
//
$_params = array(
        'username' => $username,
        'password' => $alreadyEnc ? trim($password) : self::simpleEncPass(trim($password)),
        'ip'    => self::onlineip(),
        'siteFlag' => self::$site,
        'remember' => $remember
);
$_params['checksum'] = self::_getCheckSum($_params['username'] . $_params['password'] .
$_params['ip'] . $_params['siteFlag'] . $_params['remember']);

//
// 2.調(diào)用webservice接口,進行登陸處理
//
$aRet = self::_callSoap('loginUCenter', $_params);

if (intval($aRet['resultFlag']) > 0 && $aRet['sessID']) {
//成功登陸
//設(shè)置本地session id
self::_setLocalSid($aRet['sessID']);

//設(shè)置用戶中心的統(tǒng)一session id腳本路徑
self::$_synloginScript = urldecode($aRet['script']);

$ret = $aRet['userinfo'];
} else {

$ret['status'] = $aRet['resultFlag'];
}

return $ret;
}//end of function         

//b) 用戶驗證中心的webservice服務(wù)程序,接收到登陸驗證請求后,調(diào)用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['status'];        //
$ret['resultFlag'] = $res_login;

if ($res_login < 1) {
//登陸失敗
} else {

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

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

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

//
//合作中心站回調(diào)登陸接口(設(shè)置用戶中心的統(tǒng)一session id)
//
self::_createCoSitesInfo();
$uinfo = array();
$_timestamp = time();
$_rawCode = array(
            'action' => 'setSid',
            'sid'  => $ret['sessID'],
            'time'  => $_timestamp,
);
if ($remember) {
$uinfo = array(
                'remember' => 1,
                'username' => $username,
                'password' => $password
);
}

$ret['script'] = '';
$_rawStr = http_build_query(array_merge($_rawCode, $uinfo));

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

//
// 記住已登陸戰(zhàn)
//
self::registerLoggedSite($siteFlag, $ret['sessID']);

unset($ret['userinfo']['salt']);
}

return $ret;
}

?>