1.ucenter介绍
UCenter是Comsenz旗下各个产品之间信息直接传递的一个桥梁,通过UCenter 站长可以无缝整合Comsenz系列产品,实现用户的一站式登录以及社区其他数据的交互。当然可以整合任意程序,只要自己实现接入。
http模式下,同步登陆流程如下:
web1 用client.php中的uc_user_login()去ucenter验证登陆,完成后--->
调用uc_user_synlogin()--->uc_api_post()发送到ucenter下control/user.php的onsynlogin()接口--->
返回 <script src=“”></script>字符串(如下同步登陆参数)----->
通过web1将<script>显示在页面上从而调用其他web的uc.php接口,例:"http://web2/api/uc.php?time......---->
web2/3下的api/uc.php被调用--->在各自域名下写入cookie(参数从解析code=获得)。 此时刷新web2页面------>
初始化时读取cookie并解密------>获取uid并用client.php去ucenter获取详细信息。
2.整合开始
shopnc 最新版 (需要自己实现)
tipask2.6 (已经集成)
dedecms5.7(已经集成)
关于tipask,dedecms这边就不多说,傻瓜式配置
三个整合完毕效果
shopnc整合
1.shopnc根目录下完全复制uc_client文件夹
2.根目录下复制api文件夹,修改相应参数
uc.php
<?php
define('IN_DISCUZ', TRUE);
define('UC_CLIENT_VERSION', '1.5.0'); //note UCenter 版本标识
define('UC_CLIENT_RELEASE', '20081031');
define('API_DELETEUSER', 1); //note 用户删除 API 接口开关
define('API_RENAMEUSER', 1); //note 用户改名 API 接口开关
define('API_GETTAG', 1); //note 获取标签 API 接口开关
define('API_SYNLOGIN', 1); //note 同步登录 API 接口开关
define('API_SYNLOGOUT', 1); //note 同步登出 API 接口开关
define('API_UPDATEPW', 1); //note 更改用户密码 开关
define('API_UPDATEBADWORDS', 1); //note 更新关键字列表 开关
define('API_UPDATEHOSTS', 1); //note 更新域名解析缓存 开关
define('API_UPDATEAPPS', 1); //note 更新应用列表 开关
define('API_UPDATECLIENT', 1); //note 更新客户端缓存 开关
define('API_UPDATECREDIT', 1); //note 更新用户积分 开关
define('API_GETCREDITSETTINGS', 1); //note 向 UCenter 提供积分设置 开关
define('API_GETCREDIT', 1); //note 获取用户的某项积分 开关
define('API_UPDATECREDITSETTINGS', 1); //note 更新应用积分设置 开关
define('API_RETURN_SUCCEED', '1');
define('API_RETURN_FAILED', '-1');
define('API_RETURN_FORBIDDEN', '-2');
define('SHOPNC_ROOT', substr(dirname(__FILE__), 0, -4));
//note 普通的 http 通知方式
if(!defined('IN_UC')) {
error_reporting(0);
set_magic_quotes_runtime(0);
defined('MAGIC_QUOTES_GPC') || define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
require_once SHOPNC_ROOT.'/api/config.inc.php';
$_DCACHE = $get = $post = array();
$code = @$_GET['code'];
parse_str(_authcode($code, 'DECODE', UC_KEY), $get);
if(MAGIC_QUOTES_GPC) {
$get = _stripslashes($get);
}
$timestamp = time();
if($timestamp - $get['time'] > 3600) {
exit('Authracation has expiried');
}
if(empty($get)) {
exit('Invalid Request');
}
$action = $get['action'];
require_once SHOPNC_ROOT.'/uc_client/lib/xml.class.php';
$post = xml_unserialize(file_get_contents('php://input'));
if(in_array($get['action'], array('test', 'deleteuser', 'renameuser', 'gettag', 'synlogin', 'synlogout', 'updatepw', 'updatebadwords', 'updatehosts', 'updateapps', 'updateclient', 'updatecredit', 'getcreditsettings', 'updatecreditsettings'))) {
require_once SHOPNC_ROOT.'/api/include/db_mysql.class.php';
$GLOBALS['db'] = new dbstuff;
$GLOBALS['db']->connect($dbhost, $dbuser, $dbpw, $dbname, $pconnect, true, $dbcharset);
$GLOBALS['tablepre'] = $tablepre;
unset($dbhost, $dbuser, $dbpw, $dbname, $pconnect);
$uc_note = new uc_note();
exit($uc_note->$get['action']($get, $post));
} else {
exit(API_RETURN_FAILED);
}
//note include 通知方式
} else {
require_once SHOPNC_ROOT.'/api/config.inc.php';
require_once SHOPNC_ROOT.'/api/include/db_mysql.class.php';
$GLOBALS['db'] = new dbstuff;
$GLOBALS['db']->connect($dbhost, $dbuser, $dbpw, $dbname, $pconnect, true, $dbcharset);
$GLOBALS['tablepre'] = $tablepre;
unset($dbhost, $dbuser, $dbpw, $dbname, $pconnect);
}
class uc_note {
var $dbconfig = '';
var $db = '';
var $tablepre = '';
var $appdir = '';
function _serialize($arr, $htmlon = 0) {
if(!function_exists('xml_serialize')) {
include_once SHOPNC_ROOT.'/uc_client/lib/xml.class.php';
}
return xml_serialize($arr, $htmlon);
}
function uc_note() {
$this->appdir = substr(dirname(__FILE__), 0, -4);
$this->dbconfig = $this->appdir.'api/config.inc.php';
$this->db = $GLOBALS['db'];
$this->tablepre = $GLOBALS['tablepre'];
}
function test($get, $post) {
return API_RETURN_SUCCEED;
}
function deleteuser($get, $post) {
$uids = $get['ids'];
!API_DELETEUSER && exit(API_RETURN_FORBIDDEN);
return API_RETURN_SUCCEED;
}
function renameuser($get, $post) {
$uid = $get['uid'];
$usernameold = $get['oldusername'];
$usernamenew = $get['newusername'];
if(!API_RENAMEUSER) {
return API_RETURN_FORBIDDEN;
}
return API_RETURN_SUCCEED;
}
function gettag($get, $post) {
$name = $get['id'];
if(!API_GETTAG) {
return API_RETURN_FORBIDDEN;
}
$return = array();
return $this->_serialize($return, 1);
}
function synlogin($get, $post) {
$uid = $get['uid'];
$username = $get['username'];
if(!API_SYNLOGIN) {
return API_RETURN_FORBIDDEN;
}
require __DIR__ . '/../shopnc.php';
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
$sql = "SELECT * FROM `shopnc_member` WHERE member_name = '{$get['username']}'";
$member = $GLOBALS['db']->query($sql);
$member = $GLOBALS['db']->fetch_array($member);
$_SESSION['is_login'] = '1';
$_SESSION['member_id'] = $member['member_id'];
$_SESSION['member_name']= $member['member_name'];
$_SESSION['member_email']= $member['member_email'];
}
function synlogout($get, $post) {
if(!API_SYNLOGOUT) {
return API_RETURN_FORBIDDEN;
}
require __DIR__ . '/../shopnc.php';
//note 同步登出 API 接口
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
_setcookie('Example_auth', '', -86400 * 365);
setNcCookie('msgnewnum'.$_SESSION['member_id'],'',-3600);
setNcCookie('auto_login', '', -3600);
setNcCookie('cart_goods_num','',-3600);
session_unset();
session_destroy();
}
function updatepw($get, $post) {
if(!API_UPDATEPW) {
return API_RETURN_FORBIDDEN;
}
$username = $get['username'];
$password = $get['password'];
return API_RETURN_SUCCEED;
}
function updatebadwords($get, $post) {
if(!API_UPDATEBADWORDS) {
return API_RETURN_FORBIDDEN;
}
$cachefile = $this->appdir.'./uc_client/data/cache/badwords.php';
$fp = fopen($cachefile, 'w');
$data = array();
if(is_array($post)) {
foreach($post as $k => $v) {
$data['findpattern'][$k] = $v['findpattern'];
$data['replace'][$k] = $v['replacement'];
}
}
$s = "<?php\r\n";
$s .= '$_CACHE[\'badwords\'] = '.var_export($data, TRUE).";\r\n";
fwrite($fp, $s);
fclose($fp);
return API_RETURN_SUCCEED;
}
function updatehosts($get, $post) {
if(!API_UPDATEHOSTS) {
return API_RETURN_FORBIDDEN;
}
$cachefile = $this->appdir.'./uc_client/data/cache/hosts.php';
$fp = fopen($cachefile, 'w');
$s = "<?php\r\n";
$s .= '$_CACHE[\'hosts\'] = '.var_export($post, TRUE).";\r\n";
fwrite($fp, $s);
fclose($fp);
return API_RETURN_SUCCEED;
}
function updateapps($get, $post) {
if(!API_UPDATEAPPS) {
return API_RETURN_FORBIDDEN;
}
$UC_API = $post['UC_API'];
//note 写 app 缓存文件
$cachefile = $this->appdir.'./uc_client/data/cache/apps.php';
$fp = fopen($cachefile, 'w');
$s = "<?php\r\n";
$s .= '$_CACHE[\'apps\'] = '.var_export($post, TRUE).";\r\n";
fwrite($fp, $s);
fclose($fp);
//note 写配置文件
if(is_writeable($this->appdir.'./config.inc.php')) {
$configfile = trim(file_get_contents($this->appdir.'./config.inc.php'));
$configfile = substr($configfile, -2) == '?>' ? substr($configfile, 0, -2) : $configfile;
$configfile = preg_replace("/define\('UC_API',\s*'.*?'\);/i", "define('UC_API', '$UC_API');", $configfile);
if($fp = @fopen($this->appdir.'./config.inc.php', 'w')) {
@fwrite($fp, trim($configfile));
@fclose($fp);
}
}
return API_RETURN_SUCCEED;
}
function updateclient($get, $post) {
if(!API_UPDATECLIENT) {
return API_RETURN_FORBIDDEN;
}
$cachefile = $this->appdir.'./uc_client/data/cache/settings.php';
$fp = fopen($cachefile, 'w');
$s = "<?php\r\n";
$s .= '$_CACHE[\'settings\'] = '.var_export($post, TRUE).";\r\n";
fwrite($fp, $s);
fclose($fp);
return API_RETURN_SUCCEED;
}
function updatecredit($get, $post) {
if(!API_UPDATECREDIT) {
return API_RETURN_FORBIDDEN;
}
$credit = $get['credit'];
$amount = $get['amount'];
$uid = $get['uid'];
return API_RETURN_SUCCEED;
}
function getcredit($get, $post) {
if(!API_GETCREDIT) {
return API_RETURN_FORBIDDEN;
}
}
function getcreditsettings($get, $post) {
if(!API_GETCREDITSETTINGS) {
return API_RETURN_FORBIDDEN;
}
$credits = array();
return $this->_serialize($credits);
}
function updatecreditsettings($get, $post) {
if(!API_UPDATECREDITSETTINGS) {
return API_RETURN_FORBIDDEN;
}
return API_RETURN_SUCCEED;
}
}
//note 使用该函数前需要 require_once $this->appdir.'./config.inc.php';
function _setcookie($var, $value, $life = 0, $prefix = 1) {
global $cookiepre, $cookiedomain, $cookiepath, $timestamp, $_SERVER;
setcookie(($prefix ? $cookiepre : '').$var, $value,
$life ? $timestamp + $life : 0, $cookiepath,
$cookiedomain, $_SERVER['SERVER_PORT'] == 443 ? 1 : 0);
}
function _authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
$ckey_length = 4;
$key = md5($key ? $key : UC_KEY);
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($operation == 'DECODE') {
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
return $keyc.str_replace('=', '', base64_encode($result));
}
}
function _stripslashes($string) {
if(is_array($string)) {
foreach($string as $key => $val) {
$string[$key] = _stripslashes($val);
}
} else {
$string = stripslashes($string);
}
return $string;
}
确保通信成功后,开始在shopnc中修改登录退出代码 member/control/login.php pc端
修改代码部分贴出
define('UC_CONNECT', 'mysql');
define('UC_DBHOST', 'localhost');
define('UC_DBUSER', 'root');
define('UC_DBPW', 'root');
define('UC_DBNAME', 'ucenter');
define('UC_DBCHARSET', 'utf8');
define('UC_DBTABLEPRE', '`ucenter`.uc_');
define('UC_DBCONNECT', '0');
define('UC_KEY', '98411ergsdgergkuyy65467165564GcO34bR6Bb59O23eQ0ed6bP0E457gdq7k0I8IdK3jbAbkaYfJ0i8q5p0Kel9q008');
define('UC_API', 'http://127.0.0.1/ucenter');
define('UC_CHARSET', 'utf-8');
define('UC_IP', '');
define('UC_APPID', '3');
define('UC_PPP', '20');
defined('InShopNC') or exit('Access Invalid!');
//重构redirect代码
function redirect_new($url,$e_js) {
echo $e_js."<script>".
"function redirect() {window.location.replace('$url');}\n".
"setTimeout('redirect();', 2000);\n".
"</script>";
exit();
}
/**
* 登录操作
*
*/
public function indexOp(){
Language::read("home_login_index,home_login_register");
$lang = Language::getLangContent();
$model_member = Model('member');
//检查登录状态
$model_member->checkloginMember();
if ($_GET['inajax'] == 1 && C('captcha_status_login') == '1'){
$script = "document.getElementById('codeimage').src='index.php?act=seccode&op=makecode&nchash=".getNchash()."&t=' + Math.random();";
}
$result = chksubmit(false,C('captcha_status_login'),'num');
if ($result !== false){
if ($result === -11){
showDialog($lang['login_index_login_illegal'],'','error',$script);
}elseif ($result === -12){
showDialog($lang['login_index_wrong_checkcode'],'','error',$script);
}
$login_info = array();
$login_info['user_name'] = $_POST['user_name'];
$login_info['password'] = $_POST['password'];
if(include_once BASE_ROOT_PATH.'/uc_client/client.php')
{
$ucenter_user = uc_get_user($login_info['user_name']);
if ($ucenter_user){ //ucenter有数据 又没同步到 注册
$check_member_name = $model_member->getMemberInfo(array('member_name'=>$login_info['user_name']));
if(!$check_member_name)
{
$register_info = array();
$register_info['username'] = $_POST['user_name'];
$register_info['password'] = $_POST['password'];
$register_info['password_confirm'] = $_POST['password'];
$register_info['email'] = $ucenter_user[2];
$member_info = $model_member->register($register_info);
if($member_info)
{
list($uid, $username, $password, $email) = uc_user_login($login_info['user_name'], $login_info['password']);
$ucsynlogin = uc_user_synlogin($uid);
}else
{
showDialog('中心同步用户失败','','error');
}
}else
{
list($uid, $username, $password, $email) = uc_user_login($login_info['user_name'], $login_info['password']);
$ucsynlogin = uc_user_synlogin($uid);
}
}
}
$member_info = $model_member->login($login_info);
if(isset($member_info['error'])) {
showDialog($member_info['error'],'','error',$script);
}
// 自动登录
$member_info['auto_login'] = $_POST['auto_login'];
$model_member->createSession($member_info, true);
if($_POST['is_distri_login'] == 'yes' && in_array($member_info['distri_state'],array('0'))){
redirect_new(urlDistribute('distri_join','index'), $ucsynlogin);
}
if ($_GET['inajax'] == 1){
showDialog('',$_POST['ref_url'] == '' ? 'reload' : $_POST['ref_url'],'js', $ucsynlogin);
} else {
redirect_new($_POST['ref_url'], $ucsynlogin);
}
}else{
//登录表单页面
$_pic = @unserialize(C('login_pic'));
if ($_pic[0] != ''){
Tpl::output('lpic',UPLOAD_SITE_URL_HTTPS.'/'.ATTACH_LOGIN.'/'.$_pic[array_rand($_pic)]);
}else{
Tpl::output('lpic',UPLOAD_SITE_URL_HTTPS.'/'.ATTACH_LOGIN.'/'.rand(1,4).'.jpg');
}
if(empty($_GET['ref_url'])) {
$ref_url = getReferer();
if (!preg_match('/act=login&op=logout/', $ref_url)) {
$_GET['ref_url'] = $ref_url;
}
}
Tpl::output('html_title',C('site_name').' - '.$lang['login_index_login']);
if ($_GET['inajax'] == 1){
Tpl::showpage('login_inajax','null_layout');
}else{
Tpl::showpage('login');
}
}
}
/**
* 退出操作
*
* @param int $id 记录ID
* @return array $rs_row 返回数组形式的查询结果
*/
public function logoutOp(){
Language::read("home_login_index");
$lang = Language::getLangContent();
if(include_once BASE_ROOT_PATH.'/uc_client/client.php')
{
$ucsynlogout = uc_user_synlogout();
}
// 清理COOKIE
setNcCookie('msgnewnum'.$_SESSION['member_id'],'',-3600);
setNcCookie('auto_login', '', -3600);
setNcCookie('cart_goods_num','',-3600);
session_unset();
session_destroy();
if(empty($_GET['ref_url'])){
$ref_url = getReferer();
}else {
$ref_url = $_GET['ref_url'];
}
redirect_new(LOGIN_SITE_URL . '/index.php?act=login&ref_url='.urlencode($ref_url), $ucsynlogout);
}
/**
* 会员注册页面
*
* @param
* @return
*/
public function registerOp() {
Language::read("home_login_register");
$lang = Language::getLangContent();
$model_member = Model('member');
$model_member->checkloginMember();
Tpl::output('html_title',C('site_name').' - '.$lang['login_register_join_us']);
Tpl::showpage('register');
}
/**
* 会员添加操作
*
* @param
* @return
*/
public function usersaveOp() {
Language::read("home_login_register");
$lang = Language::getLangContent();
$model_member = Model('member');
$model_member->checkloginMember();
$result = chksubmit(true,C('captcha_status_register'),'num');
if ($result){
if ($result === -11){
showDialog($lang['invalid_request'],'','error');
}elseif ($result === -12){
showDialog($lang['login_usersave_wrong_code'],'','error');
}
} else {
showDialog($lang['invalid_request'],'','error');
}
$register_info = array();
$register_info['username'] = $_POST['user_name'];
$register_info['password'] = $_POST['password'];
$register_info['password_confirm'] = $_POST['password_confirm'];
$register_info['email'] = $_POST['email'];
if(include_once BASE_ROOT_PATH.'/uc_client/client.php')
{
$activeuser = uc_get_user($register_info['username']);
if ($activeuser) {
showDialog("该用户无需注册,请直接登录",'','error');
}
$uid = uc_user_register($register_info['username'], $register_info['password'], $register_info['email']);
if($uid <= 0)
{
if($uid == -1)
{
showDialog("用户名不合法!",'','error');
exit();
}
elseif($uid == -2)
{
showDialog("包含要允许注册的词语!",'','error');
exit();
}
elseif($uid == -3)
{
showDialog("你指定的用户名 {$userid} 已存在,请使用别的用户名!",'','error');
exit();
}
elseif($uid == -5)
{
showDialog("你使用的Email 不允许注册!",'','error');
exit();
}
elseif($uid == -6)
{
showDialog("你使用的Email已经被另一帐号注册,请使其它帐号",'','error');
exit();
}
else
{
showDialog("注删失改!",'','error');
exit();
}
}
else
{
$ucsynlogin = uc_user_synlogin($uid);
}
}
$member_info = $model_member->register($register_info);
if(!isset($member_info['error'])) {
$model_member->createSession($member_info, true);
$_POST['ref_url'] = (strstr($_POST['ref_url'],'logout')=== false && !empty($_POST['ref_url']) ? $_POST['ref_url'] : urlMember('member_information', 'member'));
if ($_GET['inajax'] == 1){
showDialog('',$_POST['ref_url'] == '' ? 'reload' : $_POST['ref_url'],'js', $ucsynlogin);
} else {
redirect_new($_POST['ref_url'],$ucsynlogin);
}
} else {
showDialog($member_info['error']);
}
}
整合完毕后,会出现个问题,shopnc注册其他两个站点需要先登录一次后才能同步,原因是注册仅仅是把用户数据注册到ucenter用户表中,没有把用户数据注册到各自所属用户表中。问题找到了,如下代码
解决方案:
uc_client/model/user.php 修改
function add_user($username, $password, $email, $uid = 0, $questionid = '', $answer = '', $regip = '') {
$oldp = $password;
$regip = empty($regip) ? $this->base->onlineip : $regip;
$salt = substr(uniqid(rand()), -6);
$password = md5(md5($password).$salt);
$sqladd = $uid ? "uid='".intval($uid)."'," : '';
$sqladd .= $questionid > 0 ? " secques='".$this->quescrypt($questionid, $answer)."'," : " secques='',";
$this->db->query("INSERT INTO ".UC_DBTABLEPRE."members SET $sqladd username='$username', password='$password', email='$email', regip='$regip', regdate='".$this->base->time."', salt='$salt'");
$uid = $this->db->insert_id();
$this->db->query("INSERT INTO ".UC_DBTABLEPRE."memberfields SET uid='$uid'");
//同步注册 dede tipask
$password = md5($oldp);
if($uid)
{
file_get_contents("http://127.0.0.1/extend/ask.php?m=Home&c=Login&a=reg&key=123456&username={$username}&password={$password}&email={$email}&uid={$uid}");
file_get_contents("http://127.0.0.1/extend/dede.php?m=Home&c=Login&a=reg&key=123456&username={$username}&password={$password}&email={$email}&uid={$uid}");
}
return $uid;
}
done!
另外php单点开源推荐: