用Ucenter整合你的应用,深入了解流程
[ 2013-08-30 14:15:34 | 作者: admin ]
http://www.comsenz.com/downloads/install/ucenter
可以到phpchina查看更多关于Ucenter的文章
整合一个【测试应用】
1、下载Discuz_7.0.0_SC_UTF8.zip 和 UCenter_1.5.0_SC_UTF8.zip
其中的DZ是为了测试整合了自己的应用后,同步登陆之类的。。
2、安装(这个不用说详了吧)
安装官方安装后,会自动把ucenter和dz打通的,如图
3、添加自己的新的应用
点添加新应用,然后选自定义,然后如图(根据你自己的更改)输入
4、创建自己的测试环境
把UCenter_1.5.0_SC_UTF8(1)\advanced\examples拷贝到你的测试目录,并把advanced中的uc_client放到examples目录下~~
(1)修改config.inc.php为自己本机的配置,如下是我的,可参考
这个是我的,注意,其中的数据库配置,还有UC_KEY之类的,一定要和自定义的相同。。。
这时再去Ucenter的应用管理去看一下,如果出现如下,说明配置正确,然后再进行下面的步骤
(2)创建测试数据库ps_example,并建立如下表
(3)然后进入example目录中,打开ucexample_1.php,ucexample_2.php进行测试吧~~~!
如果顺利,应该可以看到如下(一下是运行ucexample_2.php的截图)
注册
还是继续那UC的提供的例子来分析一下
1、当你在你站点下的【某一个应用】下注册的时候,第一步首先是去ucenter下注册的
其中的这个uc_user_register又调用usercontrol类的onregister方法,如下
function onregister() {
$this->init_input();
$username = $this->input('username');
$password = $this->input('password');
$email = $this->input('email');
$questionid = $this->input('questionid');
$answer = $this->input('answer');
if(($status = $this->_check_username($username)) < 0) {
return $status;
}
if(($status = $this->_check_email($email)) < 0) {
return $status;
}
$uid = $_ENV['user']->add_user($username, $password, $email, 0, $questionid, $answer);
return $uid;
}
其中又调用usermodel的add_user方法
2、在自己的应用中注册
这样之后,example_members表中也就有条用户记录了。。
至此实现了,【同步注册】了。。。
3、不过还没完。。。虽然我们在ucenter和当前应用中都注册了用户了。。。那么【其它应用】咋办呢??
呵呵,别急,还有【激活】没讲呢。。
当你在别的网站,用这个账号第一次登陆的时候,会请求
如果$uid > 0的话,会显示让你激活的链接,而通过这个激活链接点过去之后,就会绕过uc_user_register,而只在本应用的数据库插入一条用户记录。。。
什么,激活的细节还不是很明白。。。别急,下面会专门讲登陆的,到时结合起来就明白多了。。。
登陆
1、首先是到ucenter登陆,代码如下:
它调用了usercontrol类的onlogin方法
代码很简单,和普通的登陆验证用户名,密码逻辑差不多,我就不多解释了。。这部分我主要想说明的就是流程。。
2、如果ucenter登陆成功了,再来验证【本应用】
如果成功,设置cookie标志位
3、同步登陆其他应用
其中的调用如下方法:
可见关键就是这句了。。
以我的为例,他会以JS的方式引入
继续抽丝剥茧,看是uc.php下是啥东东。。。
TNND,UC.php的代码读起来有点乱的,特别是没有注释的情况下,不过流程大致明白了。。根据传过去的code,然后解码,最后调用的是如下方法
单抽出这个函数来读,还是比较好理解的,就是判断DZ的数据库是否有对应的用户记录,
如果有的话,就设置cookie标志为【登陆】,没有的话,就设置为【待激活】...
其中的
补一句,DZ源码中的标记登陆是这条语句的
退出
看完了【登陆】,再看【退出】,就蛮容易理解了。。
1、先看代码
2、下面来分析下。。
setcookie('Example_auth', '', -86400); 这句就不多解释了,退出【本应用】
然后是uc_user_synlogout,它调用的是usercontrol类下的onsynlogout方法
不难看出,也是通过js,来实现各个应用的跨域退出的,再来看它调用的是uc.php的哪一部分吧
P3P + 置空相关cookie ===> 退出相应应用~~
修改
修改和添加的流程是差不多的。。。所以我这里简略的讲一下吧
1、API函数是
2、调用的是usercontrol类下的onedit方法,如下
3、其中的就是调用usermodel类下的edit_user方法了
嘿嘿,就是这句了
评论Feed: http://blog.xg98.com/feed.asp?q=comment&id=2110
可以到phpchina查看更多关于Ucenter的文章
整合一个【测试应用】
1、下载Discuz_7.0.0_SC_UTF8.zip 和 UCenter_1.5.0_SC_UTF8.zip
其中的DZ是为了测试整合了自己的应用后,同步登陆之类的。。
2、安装(这个不用说详了吧)
安装官方安装后,会自动把ucenter和dz打通的,如图
3、添加自己的新的应用
点添加新应用,然后选自定义,然后如图(根据你自己的更改)输入
4、创建自己的测试环境
把UCenter_1.5.0_SC_UTF8(1)\advanced\examples拷贝到你的测试目录,并把advanced中的uc_client放到examples目录下~~
(1)修改config.inc.php为自己本机的配置,如下是我的,可参考
<?php
define('UC_CONNECT', 'mysql'); // 连接 UCenter 的方式: mysql/NULL, 默认为空时为 fscoketopen()
// mysql 是直接连接的数据库, 为了效率, 建议采用 mysql
//数据库相关 (mysql 连接时, 并且没有设置 UC_DBLINK 时, 需要配置以下变量)
define('UC_DBHOST', 'localhost'); // UCenter 数据库主机
define('UC_DBUSER', 'root'); // UCenter 数据库用户名
define('UC_DBPW', ''); // UCenter 数据库密码
define('UC_DBNAME', 'ps_ucenter'); // UCenter 数据库名称
define('UC_DBCHARSET', 'utf8'); // UCenter 数据库字符集
define('UC_DBTABLEPRE', 'ps_ucenter.uc_'); // UCenter 数据库表前缀
//通信相关
define('UC_KEY', 'example2'); // 与 UCenter 的通信密钥, 要与 UCenter 保持一致
define('UC_API', 'http://localhost/project/passport/ucenter_1.5.0_sc_utf8(1)/upload');// UCenter 的 URL 地址, 在调用头像时依赖此常量
define('UC_CHARSET', 'utf8'); // UCenter 的字符集
define('UC_IP', ''); // UCenter 的 IP, 当 UC_CONNECT 为非 mysql 方式时, 并且当前应用服务器解析域名有问题时, 请设置此值
define('UC_APPID', 4); // 当前应用的 ID
//ucexample_2.php 用到的应用程序数据库连接参数
$dbhost = 'localhost'; // 数据库服务器
$dbuser = 'root'; // 数据库用户名
$dbpw = ''; // 数据库密码
$dbname = 'ps_example'; // 数据库名
$pconnect = 0; // 数据库持久连接 0=关闭, 1=打开
$tablepre = 'example_'; // 表名前缀, 同一数据库安装多个论坛请修改此处
$dbcharset = 'utf8'; // MySQL 字符集, 可选 'gbk', 'big5', 'utf8', 'latin1', 留空为按照论坛字符集设定
//同步登录 Cookie 设置
$cookiedomain = ''; // cookie 作用域
$cookiepath = '/'; // cookie 作用路径
define('UC_CONNECT', 'mysql'); // 连接 UCenter 的方式: mysql/NULL, 默认为空时为 fscoketopen()
// mysql 是直接连接的数据库, 为了效率, 建议采用 mysql
//数据库相关 (mysql 连接时, 并且没有设置 UC_DBLINK 时, 需要配置以下变量)
define('UC_DBHOST', 'localhost'); // UCenter 数据库主机
define('UC_DBUSER', 'root'); // UCenter 数据库用户名
define('UC_DBPW', ''); // UCenter 数据库密码
define('UC_DBNAME', 'ps_ucenter'); // UCenter 数据库名称
define('UC_DBCHARSET', 'utf8'); // UCenter 数据库字符集
define('UC_DBTABLEPRE', 'ps_ucenter.uc_'); // UCenter 数据库表前缀
//通信相关
define('UC_KEY', 'example2'); // 与 UCenter 的通信密钥, 要与 UCenter 保持一致
define('UC_API', 'http://localhost/project/passport/ucenter_1.5.0_sc_utf8(1)/upload');// UCenter 的 URL 地址, 在调用头像时依赖此常量
define('UC_CHARSET', 'utf8'); // UCenter 的字符集
define('UC_IP', ''); // UCenter 的 IP, 当 UC_CONNECT 为非 mysql 方式时, 并且当前应用服务器解析域名有问题时, 请设置此值
define('UC_APPID', 4); // 当前应用的 ID
//ucexample_2.php 用到的应用程序数据库连接参数
$dbhost = 'localhost'; // 数据库服务器
$dbuser = 'root'; // 数据库用户名
$dbpw = ''; // 数据库密码
$dbname = 'ps_example'; // 数据库名
$pconnect = 0; // 数据库持久连接 0=关闭, 1=打开
$tablepre = 'example_'; // 表名前缀, 同一数据库安装多个论坛请修改此处
$dbcharset = 'utf8'; // MySQL 字符集, 可选 'gbk', 'big5', 'utf8', 'latin1', 留空为按照论坛字符集设定
//同步登录 Cookie 设置
$cookiedomain = ''; // cookie 作用域
$cookiepath = '/'; // cookie 作用路径
这个是我的,注意,其中的数据库配置,还有UC_KEY之类的,一定要和自定义的相同。。。
这时再去Ucenter的应用管理去看一下,如果出现如下,说明配置正确,然后再进行下面的步骤
(2)创建测试数据库ps_example,并建立如下表
CREATE TABLE `example_members` (
`uid` int(11) NOT NULL COMMENT 'UID',
`username` char(15) default NULL COMMENT '用户名',
`admin` tinyint(1) default NULL COMMENT '是否为管理员',
PRIMARY KEY (`uid`)
) TYPE=MyISAM;
`uid` int(11) NOT NULL COMMENT 'UID',
`username` char(15) default NULL COMMENT '用户名',
`admin` tinyint(1) default NULL COMMENT '是否为管理员',
PRIMARY KEY (`uid`)
) TYPE=MyISAM;
(3)然后进入example目录中,打开ucexample_1.php,ucexample_2.php进行测试吧~~~!
如果顺利,应该可以看到如下(一下是运行ucexample_2.php的截图)
注册
还是继续那UC的提供的例子来分析一下
1、当你在你站点下的【某一个应用】下注册的时候,第一步首先是去ucenter下注册的
$uid = uc_user_register($_POST['username'], $_POST['password'], $_POST['email']);
if($uid <= 0) {
if($uid == -1) {
echo '用户名不合法';
} elseif($uid == -2) {
echo '包含要允许注册的词语';
} elseif($uid == -3) {
echo '用户名已经存在';
} elseif($uid == -4) {
echo 'Email 格式有误';
} elseif($uid == -5) {
echo 'Email 不允许注册';
} elseif($uid == -6) {
echo '该 Email 已经被注册';
} else {
echo '未定义';
}
} else {
$username = $_POST['username'];
}
if($uid <= 0) {
if($uid == -1) {
echo '用户名不合法';
} elseif($uid == -2) {
echo '包含要允许注册的词语';
} elseif($uid == -3) {
echo '用户名已经存在';
} elseif($uid == -4) {
echo 'Email 格式有误';
} elseif($uid == -5) {
echo 'Email 不允许注册';
} elseif($uid == -6) {
echo '该 Email 已经被注册';
} else {
echo '未定义';
}
} else {
$username = $_POST['username'];
}
其中的这个uc_user_register又调用usercontrol类的onregister方法,如下
function onregister() {
$this->init_input();
$username = $this->input('username');
$password = $this->input('password');
$email = $this->input('email');
$questionid = $this->input('questionid');
$answer = $this->input('answer');
if(($status = $this->_check_username($username)) < 0) {
return $status;
}
if(($status = $this->_check_email($email)) < 0) {
return $status;
}
$uid = $_ENV['user']->add_user($username, $password, $email, 0, $questionid, $answer);
return $uid;
}
其中又调用usermodel的add_user方法
function add_user($username, $password, $email, $uid = 0, $questionid = '', $answer = '') {
$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='".$this->base->onlineip."', regdate='".$this->base->time."', salt='$salt'");
$uid = $this->db->insert_id();
$this->db->query("INSERT INTO ".UC_DBTABLEPRE."memberfields SET uid='$uid'");
return $uid;
}
可见,执行这个操作后,UC_DBTABLEPRE."members 表中就会多条用户记录了$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='".$this->base->onlineip."', regdate='".$this->base->time."', salt='$salt'");
$uid = $this->db->insert_id();
$this->db->query("INSERT INTO ".UC_DBTABLEPRE."memberfields SET uid='$uid'");
return $uid;
}
2、在自己的应用中注册
if($username) {
$db->query("INSERT INTO {$tablepre}members (uid,username,admin) VALUES ('$uid','$username','0')");
//注册成功,设置 Cookie,加密直接用 uc_authcode 函数,用户使用自己的函数
setcookie('Example_auth', uc_authcode($uid."\t".$username, 'ENCODE'));
echo '注册成功<br><a href="'.$_SERVER['PHP_SELF'].'">继续</a>';
exit;
}
$db->query("INSERT INTO {$tablepre}members (uid,username,admin) VALUES ('$uid','$username','0')");
//注册成功,设置 Cookie,加密直接用 uc_authcode 函数,用户使用自己的函数
setcookie('Example_auth', uc_authcode($uid."\t".$username, 'ENCODE'));
echo '注册成功<br><a href="'.$_SERVER['PHP_SELF'].'">继续</a>';
exit;
}
这样之后,example_members表中也就有条用户记录了。。
至此实现了,【同步注册】了。。。
3、不过还没完。。。虽然我们在ucenter和当前应用中都注册了用户了。。。那么【其它应用】咋办呢??
呵呵,别急,还有【激活】没讲呢。。
当你在别的网站,用这个账号第一次登陆的时候,会请求
list($uid, $username, $password, $email) = uc_user_login($_POST['username'], $_POST['password']);
如果$uid > 0的话,会显示让你激活的链接,而通过这个激活链接点过去之后,就会绕过uc_user_register,而只在本应用的数据库插入一条用户记录。。。
什么,激活的细节还不是很明白。。。别急,下面会专门讲登陆的,到时结合起来就明白多了。。。
登陆
//通过接口判断登录帐号的正确性,返回值为数组
list($uid, $username, $password, $email) = uc_user_login($_POST['username'], $_POST['password']);
setcookie('Example_auth', '', -86400);
if($uid > 0) {
if(!$db->result_first("SELECT count(*) FROM {$tablepre}members WHERE uid='$uid'")) {
//判断用户是否存在于用户表,不存在则跳转到激活页面
$auth = rawurlencode(uc_authcode("$username\t".time(), 'ENCODE'));
echo '您需要需要激活该帐号,才能进入本应用程序<br><a href="'.$_SERVER['PHP_SELF'].'?example=register&action=activation&auth='.$auth.'">继续</a>';
exit;
}
//用户登陆成功,设置 Cookie,加密直接用 uc_authcode 函数,用户使用自己的函数
setcookie('Example_auth', uc_authcode($uid."\t".$username, 'ENCODE'));
//生成同步登录的代码
$ucsynlogin = uc_user_synlogin($uid);
echo '登录成功'.$ucsynlogin.'<br><a href="'.$_SERVER['PHP_SELF'].'">继续</a>';
exit;
} elseif($uid == -1) {
echo '用户不存在,或者被删除';
} elseif($uid == -2) {
echo '密码错';
} else {
echo '未定义';
}
list($uid, $username, $password, $email) = uc_user_login($_POST['username'], $_POST['password']);
setcookie('Example_auth', '', -86400);
if($uid > 0) {
if(!$db->result_first("SELECT count(*) FROM {$tablepre}members WHERE uid='$uid'")) {
//判断用户是否存在于用户表,不存在则跳转到激活页面
$auth = rawurlencode(uc_authcode("$username\t".time(), 'ENCODE'));
echo '您需要需要激活该帐号,才能进入本应用程序<br><a href="'.$_SERVER['PHP_SELF'].'?example=register&action=activation&auth='.$auth.'">继续</a>';
exit;
}
//用户登陆成功,设置 Cookie,加密直接用 uc_authcode 函数,用户使用自己的函数
setcookie('Example_auth', uc_authcode($uid."\t".$username, 'ENCODE'));
//生成同步登录的代码
$ucsynlogin = uc_user_synlogin($uid);
echo '登录成功'.$ucsynlogin.'<br><a href="'.$_SERVER['PHP_SELF'].'">继续</a>';
exit;
} elseif($uid == -1) {
echo '用户不存在,或者被删除';
} elseif($uid == -2) {
echo '密码错';
} else {
echo '未定义';
}
1、首先是到ucenter登陆,代码如下:
function uc_user_login($username, $password, $isuid = 0, $checkques = 0, $questionid = '', $answer = '') {
$isuid = intval($isuid);
$return = call_user_func(UC_API_FUNC, 'user', 'login', array('username'=>$username, 'password'=>$password, 'isuid'=>$isuid, 'checkques'=>$checkques, 'questionid'=>$questionid, 'answer'=>$answer));
return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
}
$isuid = intval($isuid);
$return = call_user_func(UC_API_FUNC, 'user', 'login', array('username'=>$username, 'password'=>$password, 'isuid'=>$isuid, 'checkques'=>$checkques, 'questionid'=>$questionid, 'answer'=>$answer));
return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);
}
它调用了usercontrol类的onlogin方法
function onlogin() {
$this->init_input();
$isuid = $this->input('isuid');
$username = $this->input('username');
$password = $this->input('password');
$checkques = $this->input('checkques');
$questionid = $this->input('questionid');
$answer = $this->input('answer');
if($isuid) {
$user = $_ENV['user']->get_user_by_uid($username);
} else {
$user = $_ENV['user']->get_user_by_username($username);
}
$passwordmd5 = preg_match('/^\w{32}$/', $password) ? $password : md5($password);
if(empty($user)) {
$status = -1;
} elseif($user['password'] != md5($passwordmd5.$user['salt'])) {
$status = -2;
} elseif($checkques && $user['secques'] != '' && $user['secques'] != $_ENV['user']->quescrypt($questionid, $answer)) {
$status = -3;
} else {
$status = $user['uid'];
}
$merge = $status != -1 && !$isuid && $_ENV['user']->check_mergeuser($username) ? 1 : 0;
return array($status, $user['username'], $password, $user['email'], $merge);
}
$this->init_input();
$isuid = $this->input('isuid');
$username = $this->input('username');
$password = $this->input('password');
$checkques = $this->input('checkques');
$questionid = $this->input('questionid');
$answer = $this->input('answer');
if($isuid) {
$user = $_ENV['user']->get_user_by_uid($username);
} else {
$user = $_ENV['user']->get_user_by_username($username);
}
$passwordmd5 = preg_match('/^\w{32}$/', $password) ? $password : md5($password);
if(empty($user)) {
$status = -1;
} elseif($user['password'] != md5($passwordmd5.$user['salt'])) {
$status = -2;
} elseif($checkques && $user['secques'] != '' && $user['secques'] != $_ENV['user']->quescrypt($questionid, $answer)) {
$status = -3;
} else {
$status = $user['uid'];
}
$merge = $status != -1 && !$isuid && $_ENV['user']->check_mergeuser($username) ? 1 : 0;
return array($status, $user['username'], $password, $user['email'], $merge);
}
代码很简单,和普通的登陆验证用户名,密码逻辑差不多,我就不多解释了。。这部分我主要想说明的就是流程。。
2、如果ucenter登陆成功了,再来验证【本应用】
$db->result_first("SELECT count(*) FROM {$tablepre}members WHERE uid='$uid'"))
如果成功,设置cookie标志位
setcookie('Example_auth', uc_authcode($uid."\t".$username, 'ENCODE'));
3、同步登陆其他应用
function uc_user_synlogin($uid) {
$uid = intval($uid);
$return = uc_api_post('user', 'synlogin', array('uid'=>$uid));
return $return;
}
$uid = intval($uid);
$return = uc_api_post('user', 'synlogin', array('uid'=>$uid));
return $return;
}
其中的调用如下方法:
function onsynlogin() {
$this->init_input();
$uid = $this->input('uid');
if($this->app['synlogin']) {
if($this->user = $_ENV['user']->get_user_by_uid($uid)) {
$synstr = '';
foreach($this->cache['apps'] as $appid => $app) {
if($app['synlogin'] && $app['appid'] != $this->app['appid']) {
$synstr .= '<script type="text/javascript" src="'.$app['url'].'/api/uc.php?time='.$this->time.'&code='.urlencode($this->authcode('action=synlogin&username='.$this->user['username'].'&uid='.$this->user['uid'].'&password='.$this->user['password']."&time=".$this->time, 'ENCODE', $app['authkey'])).'"></script>';
}
}
return $synstr;
}
}
return '';
}
$this->init_input();
$uid = $this->input('uid');
if($this->app['synlogin']) {
if($this->user = $_ENV['user']->get_user_by_uid($uid)) {
$synstr = '';
foreach($this->cache['apps'] as $appid => $app) {
if($app['synlogin'] && $app['appid'] != $this->app['appid']) {
$synstr .= '<script type="text/javascript" src="'.$app['url'].'/api/uc.php?time='.$this->time.'&code='.urlencode($this->authcode('action=synlogin&username='.$this->user['username'].'&uid='.$this->user['uid'].'&password='.$this->user['password']."&time=".$this->time, 'ENCODE', $app['authkey'])).'"></script>';
}
}
return $synstr;
}
}
return '';
}
可见关键就是这句了。。
$synstr .= '<script type="text/javascript" src="'.$app['url'].'/api/uc.php?time='.$this->time.'&code='.urlencode($this->authcode('action=synlogin&username='.$this->user['username'].'&uid='.$this->user['uid'].'&password='.$this->user['password']."&time=".$this->time, 'ENCODE', $app['authkey'])).'"></script>';
以我的为例,他会以JS的方式引入
http://localhost/PROJECT/PASSPORT/Discuz_7.0.0/upload/api/uc.php?time=1237444252&code=9ac8Z0%2BfjFaLyoBOUpF9v4nk8dbrRNVN3svx1pJQI%2FXelPLR%2Fyby%2Bi2bMSAr9RreZZS2Cj1lgRIXTdrMIv7TLDF6QGQiTxinivl1oEvLMSDQ8Tk0zakhxLSYfIwvHpAr7AjlOcUZcM6M51inrQSoQsqrLE64foee2PaydOVgxw
继续抽丝剥茧,看是uc.php下是啥东东。。。
TNND,UC.php的代码读起来有点乱的,特别是没有注释的情况下,不过流程大致明白了。。根据传过去的code,然后解码,最后调用的是如下方法
function synlogin($get, $post) {
$uid = $get['uid'];
$username = $get['username'];
if(!API_SYNLOGIN) {
return API_RETURN_FORBIDDEN;
}
require_once $this->appdir.'./forumdata/cache/cache_settings.php';
$cookietime = 2592000;
$discuz_auth_key = md5($_DCACHE['settings']['authkey'].$_SERVER['HTTP_USER_AGENT']);
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
$uid = intval($uid);
$query = $this->db->query("SELECT username, uid, password, secques FROM ".$this->tablepre."members WHERE uid='$uid'");
if($member = $this->db->fetch_array($query)) {
_setcookie('sid', '', -86400 * 365);
_setcookie('cookietime', $cookietime, 31536000);
_setcookie('auth', _authcode("$member[password]\t$member[secques]\t$member[uid]", 'ENCODE', $discuz_auth_key), $cookietime);
} else {
_setcookie('cookietime', $cookietime, 31536000);
_setcookie('loginuser', $username, $cookietime);
_setcookie('activationauth', _authcode($username, 'ENCODE', $discuz_auth_key), $cookietime);
}
}
$uid = $get['uid'];
$username = $get['username'];
if(!API_SYNLOGIN) {
return API_RETURN_FORBIDDEN;
}
require_once $this->appdir.'./forumdata/cache/cache_settings.php';
$cookietime = 2592000;
$discuz_auth_key = md5($_DCACHE['settings']['authkey'].$_SERVER['HTTP_USER_AGENT']);
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
$uid = intval($uid);
$query = $this->db->query("SELECT username, uid, password, secques FROM ".$this->tablepre."members WHERE uid='$uid'");
if($member = $this->db->fetch_array($query)) {
_setcookie('sid', '', -86400 * 365);
_setcookie('cookietime', $cookietime, 31536000);
_setcookie('auth', _authcode("$member[password]\t$member[secques]\t$member[uid]", 'ENCODE', $discuz_auth_key), $cookietime);
} else {
_setcookie('cookietime', $cookietime, 31536000);
_setcookie('loginuser', $username, $cookietime);
_setcookie('activationauth', _authcode($username, 'ENCODE', $discuz_auth_key), $cookietime);
}
}
单抽出这个函数来读,还是比较好理解的,就是判断DZ的数据库是否有对应的用户记录,
如果有的话,就设置cookie标志为【登陆】,没有的话,就设置为【待激活】...
其中的
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
是很有用的,不了解P3P的朋友google下吧。。。补一句,DZ源码中的标记登陆是这条语句的
dsetcookie('auth', authcode("$discuz_pw\t$discuz_secques\t$discuz_uid", 'ENCODE'), $cookietime, 1, true);
退出
看完了【登陆】,再看【退出】,就蛮容易理解了。。
1、先看代码
setcookie('Example_auth', '', -86400);
//生成同步退出的代码
$ucsynlogout = uc_user_synlogout();
//生成同步退出的代码
$ucsynlogout = uc_user_synlogout();
2、下面来分析下。。
setcookie('Example_auth', '', -86400); 这句就不多解释了,退出【本应用】
然后是uc_user_synlogout,它调用的是usercontrol类下的onsynlogout方法
function onsynlogout() {
$this->init_input();
if($this->app['synlogin']) {
$synstr = '';
foreach($this->cache['apps'] as $appid => $app) {
if($app['synlogin'] && $app['appid'] != $this->app['appid']) {
$synstr .= '<script type="text/javascript" src="'.$app['url'].'/api/uc.php?time='.$this->time.'&code='.urlencode($this->authcode('action=synlogout&time='.$this->time, 'ENCODE', $app['authkey'])).'"></script>';
}
}
return $synstr;
}
return '';
}
$this->init_input();
if($this->app['synlogin']) {
$synstr = '';
foreach($this->cache['apps'] as $appid => $app) {
if($app['synlogin'] && $app['appid'] != $this->app['appid']) {
$synstr .= '<script type="text/javascript" src="'.$app['url'].'/api/uc.php?time='.$this->time.'&code='.urlencode($this->authcode('action=synlogout&time='.$this->time, 'ENCODE', $app['authkey'])).'"></script>';
}
}
return $synstr;
}
return '';
}
不难看出,也是通过js,来实现各个应用的跨域退出的,再来看它调用的是uc.php的哪一部分吧
function synlogout($get, $post) {
if(!API_SYNLOGOUT) {
return API_RETURN_FORBIDDEN;
}
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
_setcookie('auth', '', -86400 * 365);
_setcookie('sid', '', -86400 * 365);
_setcookie('loginuser', '', -86400 * 365);
_setcookie('activationauth', '', -86400 * 365);
}
if(!API_SYNLOGOUT) {
return API_RETURN_FORBIDDEN;
}
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
_setcookie('auth', '', -86400 * 365);
_setcookie('sid', '', -86400 * 365);
_setcookie('loginuser', '', -86400 * 365);
_setcookie('activationauth', '', -86400 * 365);
}
P3P + 置空相关cookie ===> 退出相应应用~~
修改
修改和添加的流程是差不多的。。。所以我这里简略的讲一下吧
1、API函数是
uc_user_edit($username, $oldpw, $newpw, $email);
2、调用的是usercontrol类下的onedit方法,如下
function onedit() {
$this->init_input();
$username = $this->input('username');
$oldpw = $this->input('oldpw');
$newpw = $this->input('newpw');
$email = $this->input('email');
$ignoreoldpw = $this->input('ignoreoldpw');
$questionid = $this->input('questionid');
$answer = $this->input('answer');
if(!$ignoreoldpw && $email && ($status = $this->_check_email($email, $username)) < 0) {
return $status;
}
$status = $_ENV['user']->edit_user($username, $oldpw, $newpw, $email, $ignoreoldpw, $questionid, $answer);
if($newpw && $status > 0) {
$this->load('note');
$_ENV['note']->add('updatepw', 'username='.urlencode($username).'&password=');
$_ENV['note']->send();
}
return $status;
}
$this->init_input();
$username = $this->input('username');
$oldpw = $this->input('oldpw');
$newpw = $this->input('newpw');
$email = $this->input('email');
$ignoreoldpw = $this->input('ignoreoldpw');
$questionid = $this->input('questionid');
$answer = $this->input('answer');
if(!$ignoreoldpw && $email && ($status = $this->_check_email($email, $username)) < 0) {
return $status;
}
$status = $_ENV['user']->edit_user($username, $oldpw, $newpw, $email, $ignoreoldpw, $questionid, $answer);
if($newpw && $status > 0) {
$this->load('note');
$_ENV['note']->add('updatepw', 'username='.urlencode($username).'&password=');
$_ENV['note']->send();
}
return $status;
}
3、其中的就是调用usermodel类下的edit_user方法了
function edit_user($username, $oldpw, $newpw, $email, $ignoreoldpw = 0, $questionid = '', $answer = '') {
$data = $this->db->fetch_first("SELECT username, uid, password, salt FROM ".UC_DBTABLEPRE."members WHERE username='$username'");
if($ignoreoldpw) {
$isprotected = $this->db->result_first("SELECT COUNT(*) FROM ".UC_DBTABLEPRE."protectedmembers WHERE uid = '$data[uid]'");
if($isprotected) {
return -8;
}
}
if(!$ignoreoldpw && $data['password'] != md5(md5($oldpw).$data['salt'])) {
return -1;
}
$sqladd = $newpw ? "password='".md5(md5($newpw).$data['salt'])."'" : '';
$sqladd .= $email ? ($sqladd ? ',' : '')." email='$email'" : '';
if($questionid !== '') {
if($questionid > 0) {
$sqladd .= ($sqladd ? ',' : '')." secques='".$this->quescrypt($questionid, $answer)."'";
} else {
$sqladd .= ($sqladd ? ',' : '')." secques=''";
}
}
if($sqladd || $emailadd) {
$this->db->query("UPDATE ".UC_DBTABLEPRE."members SET $sqladd WHERE username='$username'");
return $this->db->affected_rows();
} else {
return -7;
}
}
$data = $this->db->fetch_first("SELECT username, uid, password, salt FROM ".UC_DBTABLEPRE."members WHERE username='$username'");
if($ignoreoldpw) {
$isprotected = $this->db->result_first("SELECT COUNT(*) FROM ".UC_DBTABLEPRE."protectedmembers WHERE uid = '$data[uid]'");
if($isprotected) {
return -8;
}
}
if(!$ignoreoldpw && $data['password'] != md5(md5($oldpw).$data['salt'])) {
return -1;
}
$sqladd = $newpw ? "password='".md5(md5($newpw).$data['salt'])."'" : '';
$sqladd .= $email ? ($sqladd ? ',' : '')." email='$email'" : '';
if($questionid !== '') {
if($questionid > 0) {
$sqladd .= ($sqladd ? ',' : '')." secques='".$this->quescrypt($questionid, $answer)."'";
} else {
$sqladd .= ($sqladd ? ',' : '')." secques=''";
}
}
if($sqladd || $emailadd) {
$this->db->query("UPDATE ".UC_DBTABLEPRE."members SET $sqladd WHERE username='$username'");
return $this->db->affected_rows();
} else {
return -7;
}
}
嘿嘿,就是这句了
$this->db->query("UPDATE ".UC_DBTABLEPRE."members SET $sqladd WHERE username='$username'");
[最后修改由 admin, 于 2013-08-30 14:37:26]

这篇日志没有评论。
此日志不可发表评论。