由于項目需要,我們需要多個二級域名問答網站對整站的内容進行獨立管理和營運。
那麼,如何實作使用者在任何一個子站或主站登入登出統一步調呢?在這裡我們首先需要共享cookie,進而實作同域單點登入,統一生成.xxx.com下的cookie,使得主站和子站用生成的cookie進行使用者身份校驗。
主要涉及三個檔案:
system/core/user.php 讀取cookie并進行解碼
app/account/ajax.php 登入後設定cookie
models/account.php 設定cookie
具體的代碼修改分以下幾塊:
1.對于主站
改動:設定主站system/class/cls_http.inc.php中setcookie函數$domain為”.xxx.com”。
public static function set_cookie($name, $value = '', $expire = null, $path = '/', $domain = null, $secure = false, $httponly = false)
{
if (! $domain and G_COOKIE_DOMAIN)
{
$domain = G_COOKIE_DOMAIN;
}
$domain = '.xxx.com';
return setcookie('jdn_' . $name, $value, $expire, $path, $domain, $secure, $httponly);
//return setcookie(G_COOKIE_PREFIX . $name, $value, $expire, $path, $domain, $secure, $httponly);
}
說明:由于不明的原因G_COOKIE_DOMAIN define無效,故設定cookie的時候直接指定域為.xxx.com
2.對于子站:
改動1:system/class/cls_http.inc.php
說明:二級域名擷取cookie必須保證名稱一緻,另外二級域名在生成cookie的時候同樣要指定域為.xxx.com。
代碼中注釋部分為代碼。
/*** 擷取 COOKIE
*
* @param $name*/
public static function get_cookie($name)
{
// if (isset($_COOKIE[G_COOKIE_PREFIX . $name]))
// {
// return $_COOKIE[G_COOKIE_PREFIX . $name];
// }
if (isset($_COOKIE['jdn_' . $name]))
{
return $_COOKIE['jdn_' . $name];
}
return false;
}
/**
* 設定 COOKIE
*
* @param $name
* @param $value
* @param $expire
* @param $path
* @param $domain
* @param $secure
* @param $httponly
*/
public static function set_cookie($name, $value = '', $expire = null, $path = '/', $domain = null, $secure = false, $httponly = false)
{
if (! $domain and G_COOKIE_DOMAIN)
{
$domain = G_COOKIE_DOMAIN;
}
$domain = '.f1bang.com';
return setcookie('jdn_' . $name, $value, $expire, $path, $domain, $secure, $httponly);
//return setcookie(G_COOKIE_PREFIX . $name, $value, $expire, $path, $domain, $secure, $httponly);
}
改動2:/system/functions.inc.php 将使用者登入資訊編譯成 hash 字元串,用于發送 Cookie
這裡的G_COOKIE_HASH_KEY同樣需要指定為一級域名的hashkey=’fwtvfmbkzamtjyq’(具體需要調試檢視主站的hashkey确定,可能會有變動)
/**
* 将使用者登入資訊編譯成 hash 字元串,用于發送 Cookie
*
* @param string
* @param string
* @param string
* @param integer
* @param boolean
* @return string
*/
function get_login_cookie_hash($user_name, $password, $salt, $uid, $hash_password = true)
{
if ($hash_password)
{
$password = compile_password($password, $salt);
}
//$auth_hash_key = md5(G_COOKIE_HASH_KEY . $_SERVER['HTTP_USER_AGENT']);
$auth_hash_key = md5('fwtvfmbkzamtjyq' . $_SERVER['HTTP_USER_AGENT']);
return H::encode_hash(array(
'uid' => $uid,
'user_name' => $user_name,
'password' => $password
), $auth_hash_key);
}
改動3:system/core/user.php 讀取cookie并進行解碼
說明:G_COOKIE_HASH_KEY如果主站的不一緻,必須指定一直,這裡為’fwtvfmbkzamtjyq’,另外還需指定cookie名jdn__user_login。
public function __construct()
{
if (AWS_APP::session()->client_info AND ! $_COOKIE['jdn__user_login'])
{
unset(AWS_APP::session()->client_info);
}
if (! AWS_APP::session()->client_info AND $_COOKIE['jdn__user_login'])
{
//$auth_hash_key = md5(G_COOKIE_HASH_KEY . $_SERVER['HTTP_USER_AGENT']);
$auth_hash_key = md5('fwtvfmbkzamtjyq' . $_SERVER['HTTP_USER_AGENT']);
// 解碼 Cookie
$sso_user_login = H::decode_hash($_COOKIE['jdn__user_login'], $auth_hash_key);
if ($sso_user_login['user_name'] AND $sso_user_login['password'] AND $sso_user_login['uid'])
{
if (AWS_APP::model('account')->check_hash_login($sso_user_login['user_name'], $sso_user_login['password']))
{
AWS_APP::session()->client_info['__CLIENT_UID'] = $sso_user_login['uid'];
AWS_APP::session()->client_info['__CLIENT_USER_NAME'] = $sso_user_login['user_name'];
AWS_APP::session()->client_info['__CLIENT_PASSWORD'] = $sso_user_login['password'];
return true;
}
}
return false;
}
}