立即注册 登录
彼岸网 返回首页

天香公主的个人空间 http://www.bian-wang.com/discuz/?10005 [收藏] [复制] [分享] [RSS] txgz999@yahoo.com

日志

Discuz系统学习:整合UCenter的应用

热度 4已有 732 次阅读2016-10-31 11:37 AM |个人分类:Discuz

据UCenter安装说明: "UCenter是一个能沟通多个应用的桥梁,使各应用共享一个用户数据库,实现统一登录,注册,用户管理"。这是个很好的想法。首先众多网站虽然功能各异,但都有注册和管理用户的需要。与其各自开发用户管理功能,不如借用一个第三方开发的公认的用户管理系统,从而把精力集中用在开发网站要提供的核心生意有关的功能上。UCenter就是这样一个系统。其次UCenter还有个特点就是它支持使用它的网站之间能自由的连接起来。在一个网站登陆后,就能跨越到其它网站而不用重新登陆,所以对用户来讲,这些网站无异于一个网站一般。

Discuz就是这样一个用UCenter来管理用户的应用。怎样才能在自己的应用里使用UCenter作为用户管理呢? 最近版的UCenter 1.6 下载文件(链接)里除了UCenter外,还带着一个这样的应用的范例。

下载文件解压后的文件夹upload里包含了可安装的UCenter服务端软件,安装后就成为一个UCenter服务端

下载文件解压后的文件夹uc_client里包含了的UCenter应用端软件,文件夹example里包含了应用范例

将文件夹uc_client拷贝到文件夹example里成为它的子文件夹,再在一个UCenter服务端的应用列表里加入这个应用,并修改它的config.ini.php文件里的内容后,example就成为了一个整合了UCenter的应用
每一个整合UCenter的应用都需要包含UCenter应用端软件uc_client作为它的一个子目录,其中含有一个重要的文件client.php。它还要有一个名叫api 的子目录,包含了一个名叫uc.php的文件,虽然文件名可通过设置来改变,但惯例是叫uc.php。 uc_client提供了两种使用UCenter服务端的办法。一种是如果可能的话直接和UCenter服务端的数据库链接,这样一来UCenter服务端做的很多事,uc_client也能同样处理,这是uc_client里含有很多与UCenter服务端同样的代码的原因。另一种办法是向UCenter服务端发post请求,这种办法应用面更广,应用和UCenter可以在不同的服务器上。client.php可以看成是UCenter服务端驻扎在应用里的代理(proxy), 它隐藏了应用端和服务端通讯的细节,它免除了应用里的代码直接和UCenter服务端联系的需要,应用里的代码只要调用它的函数就能使用UCenter服务端提供的功能。而uc.php则提供给UCenter服务端和应用联系的渠道。一般来讲uc_client包括client.php具有普适性,不同的应用都可以直接用uc_client。而uc.php则对不同的应用需要有所改动。这是因为当UCenter服务端通知它某个事件发生时,uc.php往往要有数据需要保存到应用所用的数据库里,按那里数表的不同,uc.php要做的事也不同。每个这样的应用都要在UCenter服务端里注册,


关键的一点是两者要用一个相同的通讯密钥。当一方发起和对方的联系时,它要将通话内容用这个密钥加密,对方接到加密的内容后再用该密钥解密。这样做的好处是每方都能确认和它通讯的的确是对方。但是回复里的内容一般没有加密,即便其中包含着隐秘信息,如UCenter对应用发送的用户登录请求的回复里包含着用户密码。为何不将回复也用密钥加密呢?所以要确保两者之间联系的安全性,应该给UCenter安装SSL。



下面我们以范例里的用户登陆过程为例来看一下应用是如何和UCenter联系的。


这个流程的关键点有:
1)当用户提交登录资料后,应用是请UCenter来判别该登录资料是否正确。用户向UCenter发送的信息是用只有这个应用和这个UCenter知道的通讯密钥加密的
2)应用接到UCenter对登录资料的确认后,将用户的身份(用户ID和用户名)记录到了cookie里保存在用户的浏览器里。这样以后每次用户通过浏览器和应用联系时,应用都能从它发来的cookie得知用户的身份。注意这个cookie也是用那个通讯密钥加密的,所以别人没法在浏览器里按某用户的ID和用户名来人为添加这样的cookie
3)当应用接到UCenter的确认后,它还启动了同步登录(synlogin) 即让该用户能在同一个机器的同样的浏览器里自动登录到其它用这个UCenter的应用。做法是向UCenter发一个synlogin请求,UCenter回复里包含向其它应用发请求的代码,这样这个浏览器就自动向其它那些应用发了个请求,结果是这些应用也都设置了记载用户身份的cookie。注意这些cookie不是那些应用回复用户直接请求的结果,而是由第三方应用(即这个流程里的第一个应用)提供的网页激发的,所以这是一个跨域设置,一般浏览器是不支持的,除非那些应用的回复的头部加了个p3p设置。

其中一些关键步骤的代码如下:
1. example (a.k.a. my application) 包含了用户登陆界面: examples/code/login_db.php echo '<form method="post" action="'.$_SERVER['PHP_SELF'].'?example=login">'; echo '登录:'; echo '<dl><dt>用户名</dt><dd><input name="username"></dd>'; echo '<dt>密码</dt><dd><input name="password" type="password"></dd></dl>'; echo '<input name="submit" type="submit"> '; echo '</form>'; 和对用户提交登陆资料的处理: examples/code/login_db.php //通过接口判断登录帐号的正确性,返回值为数组 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; } 2. 上面调用的uc_user_login和uc_user_synlogin都是uc_client提供的函数: client.php 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); } 当我们设置 uc_client成和uc_server通过post联系时,UC_API_FUNC的值是uc_api_post。这个函数调用了uc_fopen,在其中用PHP提供的fsockopen函数向发送了post请求: function uc_api_post($module, $action, $arg = array()) { .... $postdata = uc_api_requestdata($module, $action, $s); return uc_fopen2(UC_API.'/index.php', 500000, $postdata, '', TRUE, UC_IP, 20); } function uc_api_requestdata($module, $action, $arg='', $extra='') { $input = uc_api_input($arg); $post = "m=$module&a=$action&inajax=2&release=".UC_CLIENT_RELEASE."&input=$input&appid=".UC_APPID.$extra; return $post; } function uc_api_input($data) { $s = urlencode(uc_authcode($data.'&agent='.md5($_SERVER['HTTP_USER_AGENT'])."&time=".time(), 'ENCODE', UC_KEY)); return $s; } function uc_fopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE) { ... $out = "POST $path HTTP/1.0\r\n"; $out .= "Accept: */*\r\n"; //$out .= "Referer: $boardurl\r\n"; $out .= "Accept-Language: zh-cn\r\n"; $out .= "Content-Type: application/x-www-form-urlencoded\r\n"; $out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n"; $out .= "Host: $host\r\n"; $out .= 'Content-Length: '.strlen($post)."\r\n"; $out .= "Connection: Close\r\n"; $out .= "Cache-Control: no-cache\r\n"; $out .= "Cookie: $cookie\r\n\r\n"; $out .= $post; ... if(function_exists('fsockopen')) { $fp = @fsockopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout); } elseif (function_exists('pfsockopen')) { $fp = @pfsockopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout); } else { $fp = false; } 举例而言,当用户填写了用户名为test1和密码为123451后,应用要将下面的数据提交给UC Server验证, username=test1&password=123451&isuid=0&checkques=0&questionid=&answer= 但其实发送过去的可能是下面的数据,原来的数据以加密的形式放在了input内: m=user&a=login&inajax=2&release=20110501&input=15c4UYDcKE%2B4yS8EWSDEunpH%2FkFphKAjhIjjw2MzOJ7jqQ1mmE1Ju7yqqxqtlrAUG6D1%2FDDF7v6vjMo6zHxvhWUZ6nI09dSqfrkm0UqZiXpkvFOL4HUHoFm0XtuMnHI6%2FlvN4NN8d0DxNaYyGCCfPZF9HRFADqXCrskDRhoy5RHmFIhPFZCRuOllVLtJGfslNztQ4cWRFNh%2B9w&appid=3 3. UC Server接到post请求后的处理: 文件control/user.php里的函数onlogin: if($isuid == 1) { $user = $_ENV['user']->get_user_by_uid($username); } elseif($isuid == 2) { $user = $_ENV['user']->get_user_by_email($username); } else { $user = $_ENV['user']->get_user_by_username($username); } ... $status = $user['uid']; ... return array($status, $user['username'], $password, $user['email'], $merge); 文件control/user.php里的函数onsynlogin: foreach($this->cache['apps'] as $appid => $app) { if($app['synlogin']) { $synstr .= '<script type="text/javascript" src="'.$app['url'].'/api/'.$app['apifilename'].'?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'])).'" reload="1"></script>'; if(is_array($app['extra']['extraurl'])) foreach($app['extra']['extraurl'] as $extraurl) { $synstr .= '<script type="text/javascript" src="'.$extraurl.'/api/'.$app['apifilename'].'?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'])).'" reload="1"></script>'; ... return $synstr; 继续上面的例子,UC Server发过去的数据也是加过密的(在code中):

4. 应用对事件的处理:api/uc.php: $code = @$_GET['code']; parse_str(_authcode($code, 'DECODE', UC_KEY), $get); ... $uc_note = new uc_note(); exit($uc_note->$get['action']($get, $post)); function synlogin($get, $post) { $uid = $get['uid']; $username = $get['username']; if(!API_SYNLOGIN) 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('Example_auth', _authcode($uid."\t".$username, 'ENCODE')); }
注:本文中的代码里的<符号如果后面的字符是a的话,在它们中间加了一个不应该有的空格,以避免Discuz在保存日志时自动改变日志内容。

发表评论 评论 (56 个评论)

回复 天香公主 2017-1-30 12:07 AM
carry0987: 我知道問題出在哪裡了,我有些檔案是直接用ftp上傳的,所以才會無形中超出限額,因為有些檔案比較大,在用文件上傳插件的時候會因為上傳過慢而導致出現Bad 500錯 ...
哦,原来如此。

记得你过去建议过加个进度条,等过些天有空时我试试看。
回复 carry0987 2017-1-29 11:05 PM
天香公主: 这个设置值你近来改过吗?是不是原来不是25MB,你不久前才改成25MB的?有此问是因为我算了下你上传文件的尺寸总和,约有50-60MB,如果限额一直是25MB的话,不应 ...
我知道問題出在哪裡了,我有些檔案是直接用ftp上傳的,所以才會無形中超出限額,因為有些檔案比較大,在用文件上傳插件的時候會因為上傳過慢而導致出現Bad 500錯誤,所以我才直接用ftp上傳...至於大檔案傳輸比較慢而會導致500錯誤,不知道有什麼辦法可以解決?(例如顯示實時上傳進度,就不會以為是lag而讓系統出現500錯誤了)
回复 天香公主 2017-1-29 05:46 PM
carry0987: 那...我發的那個帖子你可以幫我看看為毛沒有反應嗎?
我不知道你是怎么加视频的,我是从工具栏里加的,见下图

如果你希望在文中加入视频地址保存后直接显示成播放器,我称之为一键贴(http://www.bian-wang.com/discuz/home.php?mod=space&uid=10005&do=blog&id=1486),但如你前面说的,你的网站应该没用一键贴。所以这样加视频的话显示成超链是正常的。
回复 天香公主 2017-1-29 11:26 AM
carry0987: 我改了設置,也上傳一張16kb的圖片,依然顯示文件無法上傳,因為你上傳的文件總尺寸已經達到了最大允許的限額: 25MB ...
这个设置值你近来改过吗?是不是原来不是25MB,你不久前才改成25MB的?有此问是因为我算了下你上传文件的尺寸总和,约有50-60MB,如果限额一直是25MB的话,不应出现这种情况。

作为测试,我刚帮你将该设置改成了100MB,然后上传了一张图片就成功了。
回复 carry0987 2017-1-29 11:10 AM
天香公主: 不知你说的'檔案'是什么文件,文件名的后缀是什么?如果你没照我说的改设置的话,你现在应该什么文件都上传不了了(除非是很小的文件,尺寸不超过限额和你已上传 ...
我改了設置,也上傳一張16kb的圖片,依然顯示文件無法上傳,因為你上傳的文件總尺寸已經達到了最大允許的限額: 25MB
回复 carry0987 2017-1-29 11:08 AM
天香公主: 你是说mp4文件?我在高级模式里点击添加视频,把你用过的 http://www.qbnehs.com/video/video_6.mp4 加到贴子里去了,没觉得有问题。见你那个网页的最后一贴 ...
那...我發的那個帖子你可以幫我看看為毛沒有反應嗎?
回复 天香公主 2017-1-29 10:13 AM
你是说mp4文件?我在高级模式里点击添加视频,把你用过的 http://www.qbnehs.com/video/video_6.mp4 加到贴子里去了,没觉得有问题。见你那个网页的最后一贴
回复 天香公主 2017-1-29 09:23 AM
carry0987: 我上傳1MB的檔案,一樣不行...無論檔案大小都無法上傳
不知你说的'檔案'是什么文件,文件名的后缀是什么?如果你没照我说的改设置的话,你现在应该什么文件都上传不了了(除非是很小的文件,尺寸不超过限额和你已上传文件尺寸总和之差),你可以上传一张1MB的图片试试
回复 carry0987 2017-1-29 03:58 AM
天香公主: 这个限额是指一个用户所有上传了的文件尺寸的总和(而不是当前要上传的文件的尺寸),所以一旦达到,该用户就没法上传任何文件了。有这样一个限额是为了防止用户 ...
我上傳1MB的檔案,一樣不行...無論檔案大小都無法上傳
回复 carry0987 2017-1-29 03:57 AM
天香公主: 哦,估计你是指 "用mejs播放器来替代失效的Discuz播放器"http://www.bian-wang.com/discuz/home.php?mod=space&uid=10005&do=blog&id=1483 吧?
我试了试在你 ...
https://www.fucknehs.com/forum.php?mod=viewthread&tid=462&page=1&extra=#pid517
回复 天香公主 2017-1-29 12:03 AM
carry0987: 咦?一鍵貼?不是....
我是指使用mejs替換discuz失效的播放器...
哦,估计你是指 "用mejs播放器来替代失效的Discuz播放器"http://www.bian-wang.com/discuz/home.php?mod=space&uid=10005&do=blog&id=1483 吧?
我试了试在你的论坛里添加音乐 http://www.stephaniequinn.com/Music/Allegro%20from%20Duet%20in%20C%20Major.mp3 和视频 http://www.mediacollege.com/video-gallery/testclips/20051210-w50s.flv 都没问题,见 https://www.fucknehs.com/forum.php?mod=viewthread&tid=459&pid=525&page=1&extra=#pid525
不知你添加什么文件时出现你说的问题?给我个该文件的url,让我试试
回复 天香公主 2017-1-28 11:35 PM
carry0987: 還有文件上傳插件好像也因為https而造成任何檔案上傳皆出現:

文件無法上傳,因為你上傳的文件總尺寸已經達到了最大允許的限額: 25MB ...
这个限额是指一个用户所有上传了的文件尺寸的总和(而不是当前要上传的文件的尺寸),所以一旦达到,该用户就没法上传任何文件了。有这样一个限额是为了防止用户滥用这个功能。你可以在管理中心的应用里找到这个插件,点击"设置",进去后加大这个限额就能继续上传了。

回复 carry0987 2017-1-27 11:29 AM
天香公主: 别客气了,是说我写的一键贴吧。我刚去浏览了下你的网站,没发现问题啊。你能不能说的具体些。给我个有问题的主题页链接让我去看看,还有你认为那上面的哪个链接 ...
咦?一鍵貼?不是....
我是指使用mejs替換discuz失效的播放器...
回复 天香公主 2017-1-26 07:21 PM
carry0987: 天香前輩,我的論壇加入https後發現帖子的影片都變成連結形式,沒有載入撥放器,html5播放器是否不支援https?
别客气了,是说我写的一键贴吧。我刚去浏览了下你的网站,没发现问题啊。你能不能说的具体些。给我个有问题的主题页链接让我去看看,还有你认为那上面的哪个链接应该载入播放器。
回复 carry0987 2017-1-26 11:02 AM
天香公主: 近来精力不济,迟复为歉。界面上看好象没啥改变。我试试点击日志里的图片依然出错。比较了新旧版本的文件。新版少带了四个插件: 纵横搜索 (cloudsearch),Discuz ...
還有文件上傳插件好像也因為https而造成任何檔案上傳皆出現:

文件無法上傳,因為你上傳的文件總尺寸已經達到了最大允許的限額: 25MB
回复 carry0987 2017-1-26 10:21 AM
天香公主: 近来精力不济,迟复为歉。界面上看好象没啥改变。我试试点击日志里的图片依然出错。比较了新旧版本的文件。新版少带了四个插件: 纵横搜索 (cloudsearch),Discuz ...
天香前輩,我的論壇加入https後發現帖子的影片都變成連結形式,沒有載入撥放器,html5播放器是否不支援https?
回复 carry0987 2017-1-25 12:22 AM
天香公主: 近来精力不济,迟复为歉。界面上看好象没啥改变。我试试点击日志里的图片依然出错。比较了新旧版本的文件。新版少带了四个插件: 纵横搜索 (cloudsearch),Discuz ...
果然如此...好吧,謝謝天香~
回复 天香公主 2017-1-25 12:01 AM
carry0987: X3.3測試的如何阿~
近来精力不济,迟复为歉。界面上看好象没啥改变。我试试点击日志里的图片依然出错。比较了新旧版本的文件。新版少带了四个插件: 纵横搜索 (cloudsearch),Discuz!联盟 (cloudunion),好贷站长联盟 (dzapp_haodai), 和旋风存储 (xf_storage)。 新版多了一个新文件source/function/function_preg.php,这个文件被function_core.php以下面的方式所用:
if(PHP_VERSION < '7.0.0') {
        function dpreg_replace($pattern, $replacement, $subject, $limit = -1, &$count) {
                return preg_replace($pattern, $replacement, $subject, $limit, $count);
        }
} else {
        function dpreg_replace($pattern, $replacement, $subject, $limit = -1, &$count) {
                require_once libfile('function/preg');
                return _dpreg_replace($pattern, $replacement, $subject, $limit, $count);
        }
}
可见是对PHP7做了优化,但仍支持PHP5。共有近200个文件有改动,不少都是很小的改动。应该没有提供任何新功能。
回复 carry0987 2017-1-21 03:35 AM
天香公主: 我看了下你的文件 config/config_ucenter.php 里有这么一句:
    define('UC_API', 'http://www.fucknehs.com/uc_server');
其中的 http 是不是得改成 https ? ...
X3.3測試的如何阿~
回复 东风 2017-1-18 04:17 PM
求救来了,天香公主。
123下一页

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 立即注册

小黑屋|Archiver|彼岸网  

Powered by Discuz! X3.1 © 2001-2014 Comsenz Inc.
GMT-4, 2017-3-30 06:27 PM , Processed in 0.061946 second(s), 21 queries.

返回顶部