OpenVZ型VPS安装Teredo接入IPv6
[
2010/04/23 23:35 | by suibing ]
2010/04/23 23:35 | by suibing ]
没有原生提供IPv6的XEN型VPS可以在Hurricane Electric申请一个TunnelBroker接入IPv6,对OpenVZ型VPS,由于目前绝大多数VPS的提供的OpenVZ内核没有打上虚拟sit0设备的补丁,所以不能使用TunnelBroker(已经可用,参阅http://www.lostriver.net/linux-userspace-6to4-tun/)。但如果VPS提供TUN/TAP设备,可以通过Teredo接入IPv6。
Linux上的开源Teredo客户端叫Miredo。对于Ubuntu/Debian,Miredo已经有了deb安装包,开启TUN/TAP后运行apt-get install miredo,再次用ifconfig查看时,名为teredo的TUN/TAP接口已经配置完成,IPv6前缀为2001:0:53aa:64c:。惟一一点遗憾是Miredo占用了约30M内存(是在保存peer list么?),对于小内存VPS有些压力。另外注意每次reboot或者重启Miredo进程后,IPv6地址将会改变。
Teredo也可以为位于IPv4 NAT内的主机提供IPv6接入(6to4必须要客户端有public IPv4 address),完整的Teredo接入需要客户端、Teredo Server和Teredo Relay。(Wiki在此)。由于需要bubble packet,国内又没有Teredo Relay(中国CERNET2内,可见的Teredo Relay位于欧洲),第一个IPv6数据包往返可能长达1000ms,后续数据包往返大约在300ms+。
Teredo接入与6to4类似,对于不同的IPv6地址使用不同的中继;不同之处是Teredo Relay在IPv6网络anycast 2001::/32前缀,而6to4 Relay除在IPv6网anycast 2002::/16,还在IPv4网络anycast 192.88.99.1。
CERNET2有线路tein3至欧洲,目前到本站IPv6的Teredo中继是funet.fi(芬兰),延时200ms+,再从芬兰到美国的VPS又加上100ms延时。带宽十分充裕,但在高峰时段丢包率达到25%,v4和v6线路都有丢包。
一般来说同时具有IPv4与IPv6地址的域名,将优先使用IPv6访问。但对于Teredo接入IPv6,系统会优先使用IPv4访问以获得更好的接入质量。所以添加IPv6域名应慎重,对于CERNET用户,系统会优先使用IPv4访问,经过几十秒超时后才使用IPv6,体验极差。
6to4可以在没有原生IPv6接入时构建IPv6 over IPv4隧道。该协议已经被linux内核所支持,内核提供了虚拟设备sit自动配置IPv6隧道。很多ISP也提供免费的TunnelBroker。但如果内核没有支持sit设备(比如现在大多数OpenVZ的VPS的内核时都没有支持sit),则在运行
# ip tunnel add 6to4 mode sit
会出现
ioctl: No such device
搜索了一下,似乎还没有运行于linux的第三方程序能建立6to4隧道,于是只好自己写一个。程序放在了
Please visit http://code.google.com/p/tb-tun/。
RFC3056包含了6to4隧道大多数细节,我只看了数据包封装,十分简单,把IPv6数据包(包括header和payload)直接作为IP数据包的packet body。注意IPv4数据包的协议类型为41(C语言里面定义常数IPPROTO_IPV6)。
程序首先创建TUN设备,并开启SOCK_RAW监听协议41(由于用了原始套接字,运行时必须要有root权限)。然后创建两个线程s2t和t2s,s2t把sock上监听到源地址正确、协议类型为41的IP包去掉包头写入TUN设备,t2s读取TUN设备上的数据并封入IP数据包作为内容发送给Relay Server。
t2s比较容易,惟一疑惑是使用sendto()函数时,远端地址结构体remoteaddr.sin_port不知道如何填写,因为封装的不是TCP或者UDP,没有端口号。填写为htons(IPPROTO_IPV6)没有出现问题。
s2t则出现了一些问题,明明向TUN设备写入了正确的数据包,却无法正确被应用程序识别,tcpdump返回wrong link-layer encapsulationbad-hlen。
重新查看了内核TUN/TAP设备的文档,原来TUN设备模拟点对点链路,也存在链路数据包头。通常创建TUN/TAP设备时使用了flag IFF_NO_PI缺省了链路层包头,内核自动把协议字填写为IP数据包。与实际的IPv6不符导致错误。
flag IFF_NO_PI没有设置时,链路附加包头为:
struct tun_pi {
unsigned short flags;
unsigned short proto;
};
flag仅在接收数据包时有效,这里向TUN设备写入,即发送数据包,这一字可以置0,proto应该填写htons(ETH_P_IPV6)。
向TUN写入时,需要在从sock读取的IPv6数据包前加入4个字节的上述结构体。t2s函数也要进行相应修改,除去上述的4个字节链路包头。
如何配置6to4 tunnel参阅Google Code上的HOWTO。试验了一下资源占用,内存占用约0.5M,CPU使用为wget的2倍。没有测试过兼容性,代码也显然还有很大改进空间
Linux上的开源Teredo客户端叫Miredo。对于Ubuntu/Debian,Miredo已经有了deb安装包,开启TUN/TAP后运行apt-get install miredo,再次用ifconfig查看时,名为teredo的TUN/TAP接口已经配置完成,IPv6前缀为2001:0:53aa:64c:。惟一一点遗憾是Miredo占用了约30M内存(是在保存peer list么?),对于小内存VPS有些压力。另外注意每次reboot或者重启Miredo进程后,IPv6地址将会改变。
Teredo也可以为位于IPv4 NAT内的主机提供IPv6接入(6to4必须要客户端有public IPv4 address),完整的Teredo接入需要客户端、Teredo Server和Teredo Relay。(Wiki在此)。由于需要bubble packet,国内又没有Teredo Relay(中国CERNET2内,可见的Teredo Relay位于欧洲),第一个IPv6数据包往返可能长达1000ms,后续数据包往返大约在300ms+。
Teredo接入与6to4类似,对于不同的IPv6地址使用不同的中继;不同之处是Teredo Relay在IPv6网络anycast 2001::/32前缀,而6to4 Relay除在IPv6网anycast 2002::/16,还在IPv4网络anycast 192.88.99.1。
CERNET2有线路tein3至欧洲,目前到本站IPv6的Teredo中继是funet.fi(芬兰),延时200ms+,再从芬兰到美国的VPS又加上100ms延时。带宽十分充裕,但在高峰时段丢包率达到25%,v4和v6线路都有丢包。
一般来说同时具有IPv4与IPv6地址的域名,将优先使用IPv6访问。但对于Teredo接入IPv6,系统会优先使用IPv4访问以获得更好的接入质量。所以添加IPv6域名应慎重,对于CERNET用户,系统会优先使用IPv4访问,经过几十秒超时后才使用IPv6,体验极差。
6to4可以在没有原生IPv6接入时构建IPv6 over IPv4隧道。该协议已经被linux内核所支持,内核提供了虚拟设备sit自动配置IPv6隧道。很多ISP也提供免费的TunnelBroker。但如果内核没有支持sit设备(比如现在大多数OpenVZ的VPS的内核时都没有支持sit),则在运行
# ip tunnel add 6to4 mode sit
会出现
ioctl: No such device
搜索了一下,似乎还没有运行于linux的第三方程序能建立6to4隧道,于是只好自己写一个。程序放在了
Please visit http://code.google.com/p/tb-tun/。
RFC3056包含了6to4隧道大多数细节,我只看了数据包封装,十分简单,把IPv6数据包(包括header和payload)直接作为IP数据包的packet body。注意IPv4数据包的协议类型为41(C语言里面定义常数IPPROTO_IPV6)。
程序首先创建TUN设备,并开启SOCK_RAW监听协议41(由于用了原始套接字,运行时必须要有root权限)。然后创建两个线程s2t和t2s,s2t把sock上监听到源地址正确、协议类型为41的IP包去掉包头写入TUN设备,t2s读取TUN设备上的数据并封入IP数据包作为内容发送给Relay Server。
t2s比较容易,惟一疑惑是使用sendto()函数时,远端地址结构体remoteaddr.sin_port不知道如何填写,因为封装的不是TCP或者UDP,没有端口号。填写为htons(IPPROTO_IPV6)没有出现问题。
s2t则出现了一些问题,明明向TUN设备写入了正确的数据包,却无法正确被应用程序识别,tcpdump返回wrong link-layer encapsulationbad-hlen。
重新查看了内核TUN/TAP设备的文档,原来TUN设备模拟点对点链路,也存在链路数据包头。通常创建TUN/TAP设备时使用了flag IFF_NO_PI缺省了链路层包头,内核自动把协议字填写为IP数据包。与实际的IPv6不符导致错误。
flag IFF_NO_PI没有设置时,链路附加包头为:
struct tun_pi {
unsigned short flags;
unsigned short proto;
};
flag仅在接收数据包时有效,这里向TUN设备写入,即发送数据包,这一字可以置0,proto应该填写htons(ETH_P_IPV6)。
向TUN写入时,需要在从sock读取的IPv6数据包前加入4个字节的上述结构体。t2s函数也要进行相应修改,除去上述的4个字节链路包头。
如何配置6to4 tunnel参阅Google Code上的HOWTO。试验了一下资源占用,内存占用约0.5M,CPU使用为wget的2倍。没有测试过兼容性,代码也显然还有很大改进空间
详解ucenter原理及第三方应用程序整合思路、方法
[
2010/03/26 16:53 | by suibing ]
2010/03/26 16:53 | by suibing ]
整合了 ucenter就等于整合了整个php界的所有php程序。
一、功用:
不对,何止整合了整个php界的所有php程序,而是整合了 ucenter就等于整合了所有的asp/asp.net/php/jsp等其它语言的所有web应用程序。(因为ucenter client的api开发包,dz会推出其它语言版)
而且所有整合的程序同步登录,同步退出,同步修改密码。最终用户可以通过它轻松通行在各个应用之中,无需重复登录、注册、退出
一个id可以出入一个站内的所有程序,如cms和bbs,也可以一个id出入www.a.com和www.b.com及www.c.com
a.com的用户可以和b.com的用户互发短消息pm,a.com的用户可以和b.com的用户加好友。
而且可以实现站内信(pm)和其它任意站的任意程序的站内信(pm)互通。
可以实现www.a.com与[url]www.b.com及www.c.com[/url]共享一个用户库,www.a.com的用户可以给www.b.com的用户pm短信.
用户组与discuz不对应的问题也得到解决。因为一般应用程序的用户组是单独的一个应用,和discuz再没有关系,而是和ucenter有关系,而ucenter没有用户组的概念。
二、整合方法:
如果单说整合用户的话,整合时应用程序的改动也非常小,原数据库不用动,原写cookies的代码不用动,原写数据库session的代码不用动,原来的程序不用怎么动,只需改动以下4个文件:
longin.php register.php logout.php 修改密码文件.php (忘记密码.php不用动,用原来的就可以)
4个文件中加上和ucenter api通信的语句和逻辑结构。
另需要针对ucenter新增加一个文件uc.php,这个文件就是应用程序接收ucenter传来的指令并执行的文件。而且他利用p3p技术实现反向登录a.com或是同时反向登录a.com/b.com/c.com的dedecms或是phpcms或是任意所有程序。
共计改4个文件,增一个文件。
如果要是整合站内信pm,好友,头像等功能,思路与方法和整合用户类同。
另外有一点,在不同的系统之间注册的用户,在第一次登录这个从来没有登录过的系统时,会让激活。借用这个激活,可以让用户完善在本应用程序中的资料,如企业注册资料。资料不完善,不可以激活。
如在bbs注册一个用户test,第一次来到b2b的程序中,这时,并不会自动登录,而是要求用户激活,而test在bbs注册时填的字段与b2b中要求的不同。这时让用户完善资料。第二次来就会自动登录。
三、 uc原理:
以用户登录为例介绍,其它注销,改密码,消息,头像,好友均类同。
1.
从用户xxx在某一应用程序的login.php,输入用户名,密码讲起。
先用uc_user_login函数到uc server验证此用户和密码,如正确,则写入session,写入cookies,并更新应用程序会员表中的登录ip,登录时间。用户感觉不到这个过程。
2.
然后通过uc_user_synlogin通知uc server 用户xxx登录成功,这个过程可能使用ajax,用户感觉不到通知过程。
3.
uc server收到这个消息后,马上命令手下,把xxx登录的消息,像令牌环一样,发给所有愿意接收(后台中那个是否开启同步登录)这个消息的其它应用程序。其实就是带参数访问一下各应用程序的uc.php,用户感觉不到这个过程。
4.
各应用程序靠api下的uc.php来接收uc server发来的消息,并对uc server言听计从,让干什么就干什么。现在,收到让xxx用户在你的程序中登录的命令,马上执行。
并写本应用程序的session,并且使用p3p, 写入相同域或不同域的cookies. 用户感觉不到这个过程。
5.最后所有和uc整合的程序,xxx均登录成功。用户从www.test.com/bbs登录后, 跳到www.test.com/news同样显示登录。因为bbs 和news系统在后台均已登录。
6.应用程序与uc server的会话结束。
得益于uc设计的精巧过程,整个过程,用户完全感觉不到ucenter的存在.这是整合程序历史上的创新。完
一、功用:
不对,何止整合了整个php界的所有php程序,而是整合了 ucenter就等于整合了所有的asp/asp.net/php/jsp等其它语言的所有web应用程序。(因为ucenter client的api开发包,dz会推出其它语言版)
而且所有整合的程序同步登录,同步退出,同步修改密码。最终用户可以通过它轻松通行在各个应用之中,无需重复登录、注册、退出
一个id可以出入一个站内的所有程序,如cms和bbs,也可以一个id出入www.a.com和www.b.com及www.c.com
a.com的用户可以和b.com的用户互发短消息pm,a.com的用户可以和b.com的用户加好友。
而且可以实现站内信(pm)和其它任意站的任意程序的站内信(pm)互通。
可以实现www.a.com与[url]www.b.com及www.c.com[/url]共享一个用户库,www.a.com的用户可以给www.b.com的用户pm短信.
用户组与discuz不对应的问题也得到解决。因为一般应用程序的用户组是单独的一个应用,和discuz再没有关系,而是和ucenter有关系,而ucenter没有用户组的概念。
二、整合方法:
如果单说整合用户的话,整合时应用程序的改动也非常小,原数据库不用动,原写cookies的代码不用动,原写数据库session的代码不用动,原来的程序不用怎么动,只需改动以下4个文件:
longin.php register.php logout.php 修改密码文件.php (忘记密码.php不用动,用原来的就可以)
4个文件中加上和ucenter api通信的语句和逻辑结构。
另需要针对ucenter新增加一个文件uc.php,这个文件就是应用程序接收ucenter传来的指令并执行的文件。而且他利用p3p技术实现反向登录a.com或是同时反向登录a.com/b.com/c.com的dedecms或是phpcms或是任意所有程序。
共计改4个文件,增一个文件。
如果要是整合站内信pm,好友,头像等功能,思路与方法和整合用户类同。
另外有一点,在不同的系统之间注册的用户,在第一次登录这个从来没有登录过的系统时,会让激活。借用这个激活,可以让用户完善在本应用程序中的资料,如企业注册资料。资料不完善,不可以激活。
如在bbs注册一个用户test,第一次来到b2b的程序中,这时,并不会自动登录,而是要求用户激活,而test在bbs注册时填的字段与b2b中要求的不同。这时让用户完善资料。第二次来就会自动登录。
三、 uc原理:
以用户登录为例介绍,其它注销,改密码,消息,头像,好友均类同。
1.
从用户xxx在某一应用程序的login.php,输入用户名,密码讲起。
先用uc_user_login函数到uc server验证此用户和密码,如正确,则写入session,写入cookies,并更新应用程序会员表中的登录ip,登录时间。用户感觉不到这个过程。
2.
然后通过uc_user_synlogin通知uc server 用户xxx登录成功,这个过程可能使用ajax,用户感觉不到通知过程。
3.
uc server收到这个消息后,马上命令手下,把xxx登录的消息,像令牌环一样,发给所有愿意接收(后台中那个是否开启同步登录)这个消息的其它应用程序。其实就是带参数访问一下各应用程序的uc.php,用户感觉不到这个过程。
4.
各应用程序靠api下的uc.php来接收uc server发来的消息,并对uc server言听计从,让干什么就干什么。现在,收到让xxx用户在你的程序中登录的命令,马上执行。
并写本应用程序的session,并且使用p3p, 写入相同域或不同域的cookies. 用户感觉不到这个过程。
5.最后所有和uc整合的程序,xxx均登录成功。用户从www.test.com/bbs登录后, 跳到www.test.com/news同样显示登录。因为bbs 和news系统在后台均已登录。
6.应用程序与uc server的会话结束。
得益于uc设计的精巧过程,整个过程,用户完全感觉不到ucenter的存在.这是整合程序历史上的创新。完
Ucenter 会员同步登录通讯原理
[
2010/03/26 16:52 | by suibing ]
2010/03/26 16:52 | by suibing ]
1,用户登录bbs,通过logging.php文件中,使用函数uc_user_login验证,如果验证成功,将调用函数uc_user_synlogin(位于uc_client下的client.php文件中),在这个函数中调用 uc_api_post('user', 'synlogin', array('uid'=>$uid));之后向UC_API.'/index.php'传递了数据;这里的UC_API就是在config.inc.php中的定义的uc_server之URL地址
2,uc_server的index.php接受参数数据,获得model为user,action为synlogin,就调用control目录下的user.php类中的onsynlogin方法,通过foreach循环,以javascript的方式通知uc应用列表中的应用同步登录;即通过get方式传递给应用目录中api下的uc.php一些数据;
3,uc.php接收通知并处理get过来的数据,并在函数synlogin(位于uc.php中)通过函数_authcode加密数据(默认以UC_KEY作为密钥),用函数_setcookie设置cookie;
4,各个应用在适当的文件中用对应的密钥解码上面设置的cookie,得到用户id等数据;通过这个值来判断用户是否经过其它应用登录过;

以discuz举例:
一、用户登录检查与用户登录验证logging.php
在bbs的logging.php中如下代码段
} elseif($action == 'login') {
if($discuz_uid) {
$ucsynlogin = '';
showmessage('login_succeed', $indexname);
}
检查用户id变量$discuz_uid是否为空来判断,用户是否登录(包括从别的应用登录。)
如果用户从bbs登录,则在登录验证成功后通过如下代码:
$ucsynlogin = $allowsynlogin ? uc_user_synlogin($discuz_uid) : '';
通知其它应用----“用户已从bbs登录,请通知其它应用设置cookie”
(uc_server通过javascript调用方式向其它应用的api/uc.php传递数据)
可以在uc应用目录下新建一个名为test.php的文件,来模拟登录成功,请求uc_server通知其它应用。文件内容为:
---------------------文件内容开始----------------------
include_once "config.inc.php";
include_once "./uc_client/client.php";
echo uc_user_synlogin(1);
echo "
?>
---------------------文件内容结束----------------------
ps:这段测试代码还可以测试同步登录不好使的情况,具体使用方法,你可以思考一下(本文后面也有介绍),有问题可以在此文结尾发表评论与我讨论。
运行后,查看源代码即可看到javascript;
这里要注意了:这些javascript的通知中是不包含用户登录的应用的。也就是说只"通知"用户未登录的应用,因为用户通过uc_server登录成功的当前应用,当然不需要uc_server再通知了。具体代码请参看:webroot\uc_server\control\user.php中的onsynlogin函数的这句:
if($app['synlogin'] && $app['appid'] != $this->app['appid'])
代码解释:
$app['synlogin']是uc应用是否允许同步登录
而且应用id不等于用户当前登录的应用id
$app数组就是uc_server\data\cache\apps.php中的数组$_CACHE['apps'];
$this->app就是用户登录的应用
二、接受其它应用的同步登录通知:
在discuz的api目录下的uc.php中的函数synlogin,在这里接受uc_server发送过来的“同步登录通知”,并设置discuz的cookie,在这个函数中你可以查看到cookie的加密密钥的“算法”;
如果你想看看uc_server发送过的的“通知”是什么数据,你可以这么做:
1,修改要接受通知的应用目录下的api\uc.php,在$action = $get['action'];代码下面添加如下代码:
echo "
api\uc.php");
2,将上面建立的test.php文件放置在其它允许同步登录的应用目录下,并在浏览器中运行,然后点击页面中对应第一步的应用链接,即可看到uc_server“通知”给改应用的数据;
---------------------------分割线-------------------------------
function synlogin($get, $post)
在这个函数中通过_authcode函数,以密钥$discuz_auth_key加密了cookie;
在这里为了避免cookie名称冲突,在cookie名称(一般为:auth)前加了前缀($cookiepre),这个前缀也就是在config.inc.php中设置的那个cookie前缀值;
请看设置cookie的函数_setcookie:
(通过参数$prefix来判断是否对cookie名称添加前缀$cookiepre)
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);
}
密钥“算法”:
$discuz_auth_key= md5($_DCACHE['settings']['authkey'].$_SERVER['HTTP_USER_AGENT']);
也就是不同用户加密cookie的密钥可能不同;
三、检查用户是否已登录(无论是那个应用下登录):
discuz的include目录中common.inc.php中有这样的代码:
$discuz_auth_key = md5($_DCACHE['settings']['authkey'].$_SERVER['HTTP_USER_AGENT']);
list($discuz_pw, $discuz_secques, $discuz_uid) = empty($_DCOOKIE['auth']) ? array('', '', 0) : daddslashes(explode("\t", authcode($_DCOOKIE['auth'], 'DECODE')), 1);
这段代码就是解码在uc.php中用密钥($discuz_auth_key)加密的cookie值,以获得用户id($discuz_uid)
这里的解密函数位于bbs\include\global.func.php中,虽然未给函数传递cookie密钥,但函数中通过全局变量$GLOBALS['discuz_auth_key'])获得密钥。
2,uc_server的index.php接受参数数据,获得model为user,action为synlogin,就调用control目录下的user.php类中的onsynlogin方法,通过foreach循环,以javascript的方式通知uc应用列表中的应用同步登录;即通过get方式传递给应用目录中api下的uc.php一些数据;
3,uc.php接收通知并处理get过来的数据,并在函数synlogin(位于uc.php中)通过函数_authcode加密数据(默认以UC_KEY作为密钥),用函数_setcookie设置cookie;
4,各个应用在适当的文件中用对应的密钥解码上面设置的cookie,得到用户id等数据;通过这个值来判断用户是否经过其它应用登录过;
以discuz举例:
一、用户登录检查与用户登录验证logging.php
在bbs的logging.php中如下代码段
} elseif($action == 'login') {
if($discuz_uid) {
$ucsynlogin = '';
showmessage('login_succeed', $indexname);
}
检查用户id变量$discuz_uid是否为空来判断,用户是否登录(包括从别的应用登录。)
如果用户从bbs登录,则在登录验证成功后通过如下代码:
$ucsynlogin = $allowsynlogin ? uc_user_synlogin($discuz_uid) : '';
通知其它应用----“用户已从bbs登录,请通知其它应用设置cookie”
(uc_server通过javascript调用方式向其它应用的api/uc.php传递数据)
可以在uc应用目录下新建一个名为test.php的文件,来模拟登录成功,请求uc_server通知其它应用。文件内容为:
---------------------文件内容开始----------------------
include_once "config.inc.php";
include_once "./uc_client/client.php";
echo uc_user_synlogin(1);
echo "
";";
var_dump($_COOKIE);
echo "
?>
---------------------文件内容结束----------------------
ps:这段测试代码还可以测试同步登录不好使的情况,具体使用方法,你可以思考一下(本文后面也有介绍),有问题可以在此文结尾发表评论与我讨论。
运行后,查看源代码即可看到javascript;
这里要注意了:这些javascript的通知中是不包含用户登录的应用的。也就是说只"通知"用户未登录的应用,因为用户通过uc_server登录成功的当前应用,当然不需要uc_server再通知了。具体代码请参看:webroot\uc_server\control\user.php中的onsynlogin函数的这句:
if($app['synlogin'] && $app['appid'] != $this->app['appid'])
代码解释:
$app['synlogin']是uc应用是否允许同步登录
而且应用id不等于用户当前登录的应用id
$app数组就是uc_server\data\cache\apps.php中的数组$_CACHE['apps'];
$this->app就是用户登录的应用
二、接受其它应用的同步登录通知:
在discuz的api目录下的uc.php中的函数synlogin,在这里接受uc_server发送过来的“同步登录通知”,并设置discuz的cookie,在这个函数中你可以查看到cookie的加密密钥的“算法”;
如果你想看看uc_server发送过的的“通知”是什么数据,你可以这么做:
1,修改要接受通知的应用目录下的api\uc.php,在$action = $get['action'];代码下面添加如下代码:
echo "
";var_dump($get);echo "";die("
api\uc.php");
2,将上面建立的test.php文件放置在其它允许同步登录的应用目录下,并在浏览器中运行,然后点击页面中对应第一步的应用链接,即可看到uc_server“通知”给改应用的数据;
---------------------------分割线-------------------------------
function synlogin($get, $post)
在这个函数中通过_authcode函数,以密钥$discuz_auth_key加密了cookie;
在这里为了避免cookie名称冲突,在cookie名称(一般为:auth)前加了前缀($cookiepre),这个前缀也就是在config.inc.php中设置的那个cookie前缀值;
请看设置cookie的函数_setcookie:
(通过参数$prefix来判断是否对cookie名称添加前缀$cookiepre)
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);
}
密钥“算法”:
$discuz_auth_key= md5($_DCACHE['settings']['authkey'].$_SERVER['HTTP_USER_AGENT']);
也就是不同用户加密cookie的密钥可能不同;
三、检查用户是否已登录(无论是那个应用下登录):
discuz的include目录中common.inc.php中有这样的代码:
$discuz_auth_key = md5($_DCACHE['settings']['authkey'].$_SERVER['HTTP_USER_AGENT']);
list($discuz_pw, $discuz_secques, $discuz_uid) = empty($_DCOOKIE['auth']) ? array('', '', 0) : daddslashes(explode("\t", authcode($_DCOOKIE['auth'], 'DECODE')), 1);
这段代码就是解码在uc.php中用密钥($discuz_auth_key)加密的cookie值,以获得用户id($discuz_uid)
这里的解密函数位于bbs\include\global.func.php中,虽然未给函数传递cookie密钥,但函数中通过全局变量$GLOBALS['discuz_auth_key'])获得密钥。
说说ucenter的单点登录
[
2010/03/26 16:49 | by suibing ]
2010/03/26 16:49 | by suibing ]
所谓单点登录,无非就是几个站点共用一个用户中心,实现同步登陆,同步退出。
服务器端:Loog SSO (作者:七夜)。
客服端: ucenter,说实话dz商业化确实让php发展了不少。
ucenter 基本原理:
其实最终还是 用户去登录 只是采用了ajax 用户不会发现。
我们来看看和ucenter的具体程序:
config.php
PHP代码
define('UC_CONNECT', 'mysql'); // 连接 UCenter 的方式: mysql/NULL, 默认为空时为fscoketopen()
//数据库相关 (mysql 连接时, 并且没有设置 UC_DBLINK 时, 需要配置以下变量)
define('UC_DBHOST', 'localhost'); // UCenter 数据库主机
define('UC_DBUSER', 'root'); // UCenter 数据库用户名
define('UC_DBPW', '123'); // UCenter 数据库密码
define('UC_DBNAME', 'ucenter'); // UCenter 数据库名称
define('UC_DBCHARSET', 'utf8'); // UCenter 数据库字符集
define('UC_DBTABLEPRE', 'ucenter.uc_'); // UCenter 数据库表前缀
define('UC_KEY', 'safefewfef'); // 与 UCenter 的通信密钥, 要与 UCenter 保持一致
define('UC_API', 'http://www.taoav.com/uc');// UCenter 的 URL 地址, 在调用头像时依赖此常量
define('UC_CHARSET', 'utf-8'); // UCenter 的字符集
define('UC_IP', '127.0.0.1'); // UCenter 的 IP, 当 UC_CONNECT 为非 mysql 方式时, 并且当前应用服务器解析域名有问题时, 请设置此值
define('UC_APPID', '3'); // 对应到ucenter当前应用的 ID
define('UCDOMAIN','http://www.taoav.com/'); // 域名设置
//一些 Cookie 设置
$_UC = array();
$_UC["cookiedomain"] = ''; // cookie 作用域
$_UC["cookiepath"] = '/'; // cookie 作用路径
$_UC["cookiepre"] = 'uc_'; // cookie 前缀
$_UC["cookietime"] = '31536000'; //cookie 作用时间
配置文件写好后,到ucenter后台里面添加一个应用记住是自定义的 ‘UC_KEY’必须和config.php里面相同
接下来就是你的主目录下的api/uc.php
例如应用url 填写为 http://www.taoav.com 那么我就有对应的http://www.taoav.com/api/uc.php
如果要自定义的话 请确认你的对应关系。
最重要的就是api/uc.php ,同步登录就是访问各个应用的uc.php 关于这个dz已经给了demo
developguide
PHP代码
define('API_DELETEUSER',0); //note 用户删除 API 接口开关
define('API_RENAMEUSER', 0); //note 用户改名 API 接口开关
define('API_GETTAG', 0); //note 获取标签 API 接口开关
define('API_SYNLOGIN', 1); //note 同步登录 API 接口开关
define('API_SYNLOGOUT', 1); //note 同步登出 API 接口开关
define('API_UPDATEPW', 0); //note 更改用户密码 开关
define('API_UPDATEBADWORDS', 0); //note 更新关键字列表 开关
define('API_UPDATEHOSTS', 0); //note 更新域名解析缓存 开关
define('API_UPDATEAPPS', 0); //note 更新应用列表 开关
define('API_UPDATECLIENT', 0); //note 更新客户端缓存 开关
define('API_UPDATECREDIT', 0); //note 更新用户积分 开关
define('API_GETCREDITSETTINGS', 0); //note 向 UCenter 提供积分设置 开关
define('API_GETCREDIT',0); //note 获取用户的某项积分 开关
define('API_UPDATECREDITSETTINGS', 0); //note 更新应用积分设置 开关
这些参数都是向别的应用提供的功能开关
最后关于 自己的页面如何同步登录 别的应用
PHP代码
include_once '../config.php';
include_once '../uc_client/client.php';
你的验证登录部分
list($uid, $username, $password) = uc_user_login($_POST[username], $_POST[password]);//进入ucenter验证
$ucsynlogin = uc_user_synlogin($uid);//同步登录
echo $ucsynlogin;//因为是ajax 要echo
只用php,康盛的解决方案是比较不错的了,而且利用了p3p头实现了 不同域名 单点登录
缺点就是采用ajax 客服端请求 ,如果有10个以上应用,登录速度就慢下来了。这时候就可以考虑下七夜的Loong SSO
了解了以上的东东 php的CMS和ucenter通信 就不难了
服务器端:Loog SSO (作者:七夜)。
客服端: ucenter,说实话dz商业化确实让php发展了不少。
ucenter 基本原理:
其实最终还是 用户去登录 只是采用了ajax 用户不会发现。
我们来看看和ucenter的具体程序:
config.php
PHP代码
define('UC_CONNECT', 'mysql'); // 连接 UCenter 的方式: mysql/NULL, 默认为空时为fscoketopen()
//数据库相关 (mysql 连接时, 并且没有设置 UC_DBLINK 时, 需要配置以下变量)
define('UC_DBHOST', 'localhost'); // UCenter 数据库主机
define('UC_DBUSER', 'root'); // UCenter 数据库用户名
define('UC_DBPW', '123'); // UCenter 数据库密码
define('UC_DBNAME', 'ucenter'); // UCenter 数据库名称
define('UC_DBCHARSET', 'utf8'); // UCenter 数据库字符集
define('UC_DBTABLEPRE', 'ucenter.uc_'); // UCenter 数据库表前缀
define('UC_KEY', 'safefewfef'); // 与 UCenter 的通信密钥, 要与 UCenter 保持一致
define('UC_API', 'http://www.taoav.com/uc');// UCenter 的 URL 地址, 在调用头像时依赖此常量
define('UC_CHARSET', 'utf-8'); // UCenter 的字符集
define('UC_IP', '127.0.0.1'); // UCenter 的 IP, 当 UC_CONNECT 为非 mysql 方式时, 并且当前应用服务器解析域名有问题时, 请设置此值
define('UC_APPID', '3'); // 对应到ucenter当前应用的 ID
define('UCDOMAIN','http://www.taoav.com/'); // 域名设置
//一些 Cookie 设置
$_UC = array();
$_UC["cookiedomain"] = ''; // cookie 作用域
$_UC["cookiepath"] = '/'; // cookie 作用路径
$_UC["cookiepre"] = 'uc_'; // cookie 前缀
$_UC["cookietime"] = '31536000'; //cookie 作用时间
配置文件写好后,到ucenter后台里面添加一个应用记住是自定义的 ‘UC_KEY’必须和config.php里面相同
接下来就是你的主目录下的api/uc.php
例如应用url 填写为 http://www.taoav.com 那么我就有对应的http://www.taoav.com/api/uc.php
如果要自定义的话 请确认你的对应关系。
最重要的就是api/uc.php ,同步登录就是访问各个应用的uc.php 关于这个dz已经给了demo
developguide
PHP代码
define('API_DELETEUSER',0); //note 用户删除 API 接口开关
define('API_RENAMEUSER', 0); //note 用户改名 API 接口开关
define('API_GETTAG', 0); //note 获取标签 API 接口开关
define('API_SYNLOGIN', 1); //note 同步登录 API 接口开关
define('API_SYNLOGOUT', 1); //note 同步登出 API 接口开关
define('API_UPDATEPW', 0); //note 更改用户密码 开关
define('API_UPDATEBADWORDS', 0); //note 更新关键字列表 开关
define('API_UPDATEHOSTS', 0); //note 更新域名解析缓存 开关
define('API_UPDATEAPPS', 0); //note 更新应用列表 开关
define('API_UPDATECLIENT', 0); //note 更新客户端缓存 开关
define('API_UPDATECREDIT', 0); //note 更新用户积分 开关
define('API_GETCREDITSETTINGS', 0); //note 向 UCenter 提供积分设置 开关
define('API_GETCREDIT',0); //note 获取用户的某项积分 开关
define('API_UPDATECREDITSETTINGS', 0); //note 更新应用积分设置 开关
这些参数都是向别的应用提供的功能开关
最后关于 自己的页面如何同步登录 别的应用
PHP代码
include_once '../config.php';
include_once '../uc_client/client.php';
你的验证登录部分
list($uid, $username, $password) = uc_user_login($_POST[username], $_POST[password]);//进入ucenter验证
$ucsynlogin = uc_user_synlogin($uid);//同步登录
echo $ucsynlogin;//因为是ajax 要echo
只用php,康盛的解决方案是比较不错的了,而且利用了p3p头实现了 不同域名 单点登录
缺点就是采用ajax 客服端请求 ,如果有10个以上应用,登录速度就慢下来了。这时候就可以考虑下七夜的Loong SSO
了解了以上的东东 php的CMS和ucenter通信 就不难了
kloxo/lxadmin 安装步骤
[
2010/03/25 21:09 | by suibing ]
2010/03/25 21:09 | by suibing ]
卸载Mysql
# rpm -qa | grep mysql
卸载Apache
# rpm -qa | grep httpd
卸载PHP
# rpm -qa | grep php
wget http://download.lxlabs.com/download/kloxo/production/kloxo-install-master.sh
sh ./kloxo-install-master.sh
yum install php-bcmath php-mhash php-mbstring
# rpm -qa | grep mysql
卸载Apache
# rpm -qa | grep httpd
卸载PHP
# rpm -qa | grep php
wget http://download.lxlabs.com/download/kloxo/production/kloxo-install-master.sh
sh ./kloxo-install-master.sh
yum install php-bcmath php-mhash php-mbstring





