求助CI框架下的单点登陆实现
研究了好多天了,网上参考了很多资料,做了一些demo,还是不能真正的实现,求谁又经验的给予帮助,回帖讨论,或者加QQ交流本帖最后由 52lin 于 2018-6-21 09:30 编辑
假如域名为abc.com
登录入口统一为login.abc.com登录,登录成功后,设置一个登录cookie就好了,作用域为.abc.com
这样*.abc.com各域名下都是登录状态
如果还有其他域名也要同步登录,如域名为def.com,那么在login.abc.com登录成功的提示页面多加个<script src="http://api.def.com/sync/login?u={uid}&t={timestamp}&sign={sign}"></script>
这个script的src呢,作用主要就是生成def.com域名下的登录cookie,让def.com域名实现与abc.com同步登录,当然上面的script也可以换成iframe。
如果login.abc.com页面是ajax登录,那么上面的script的src可以在login.abc.com登录成功后的逻辑里使用CURL请求同步登录def.com
另外:u={uid}&t={timestamp}&s={sign}
{uid}为已经成功登录abc.com站点的用户id
{timestamp}为已经成功登录abc.com站点时的时间戳
{sign}为请求 s 参数之外的其他参数的加密串,加密方式你可以根据自己喜好(比如:MD5({uid}.{timestamp}.{KEY}),{KEY}为一个共同的秘钥,或者使用openssl_encrypt)
sync/login:首先要通过获取到的sign验证数据是否合法(还可以验证站点来源域名,ip等,如果需要的话)
验证通过后,也就写个def.com域名下的登录cookie就可以了
也许还有其他方法,有请楼下跟帖{:1_1:}
52lin 发表于 2018-6-21 08:59
假如域名为abc.com
登录入口统一为login.abc.com登录,登录成功后,设置一个登录cookie就好了,作用域为.ab ...
谢谢,这个方式,虽然我还没有实践,但是看你说明的逻辑,针对用户主动登陆/退出(用户点击登陆或者点击退出)应该是没有问题的,我有一个疑问:如何处理登陆后的状态实时同步?
我举个例子来说明问题:
1. 该系统需要自动退出机制——用户10分钟没有任何操作就自动退出登陆(这是很常见的做法)
2. 用户通过login.abc.com已经登陆,这时abc.com 和def.com都是登陆状态了,也记录了登陆时间。
3. 用户在def.com上面操作了5分钟时间后停止操作,并且离开了7分钟。
4. 用户回到电脑前,直接开始在abc.com上面操作。
那么问题是:
用户在第3步的时候,def.com记录的是用户已经停止7分钟没有操作了,此时还在登陆状态。
用户在第4步的时候,abc.com记录的应该是用户已经停止12分钟没有操作,按照10分钟自动退出的规则已经变成退出状态。
这两个域直接的状态如何保持同步呢?
badapple0412 发表于 2018-6-21 11:08
谢谢,这个方式,虽然我还没有实践,但是看你说明的逻辑,针对用户主动登陆/退出(用户点击登陆或者点击 ...
如果不是硬性要求的话,每个站点都设置cookie有效期为10分钟就好了。
如果要求每个站点都共同受限于这个10分钟的话,可以缓存下来
(可以使用文件缓存,memcache等等,或者存数据库),登录站点,
登录成功后,更新该用户的自动登出的时间为当前时间+10分钟,
并设置各站点的登录cookie为关闭浏览器失效。
各个站点判断是否登录的逻辑里,如果还是登录状态,
并且在自动登出的时间范围内,则更新该用户的自动登出的时间为当前时间+10分钟,反之跳转到登录页。
这样应该能够达到你的要求 给你贴点代码,自己研究下服务器端代码,位置在 index.php/welcome/uon
public function uon(){
$fltime=30;//接受AJAX时间:1分钟
$kicktime=70;//转移页面1.5分钟认为不在线
// read_file($file);
$lasttime =file_get_contents('./userfiles/time.dat');//上次时间
$now=time();
$bonline=isset($_SESSION['id']);
if ($lasttime+$fltime<$now)
{//uarr:key:IP,lastactive
$onlineuarr = file_get_contents('./userfiles/user.dat');
if (($onlineuarr=='')&&!$bonline)
{
//echo json_encode(array('c'=>0));//0无在线无登陆
exit;
}
if ($onlineuarr)
{
$onlineuarr=unserialize($onlineuarr);
}
$oldarr=$onlineuarr;
if ($bonline)//如果是登陆状态,则先进行更新active时间
{
$uid=$_SESSION['id'];
$ip=$this->input->ip_address();
if (!isset($onlineuarr[$uid]))
{
$onlineuarr[$uid]=array($ip,$now);
}else {
if ($ip==$onlineuarr[$uid])
{
$onlineuarr[$uid]=$now;
}else{
$this->ion_auth->logout();
echo json_encode(array('ip'=>$onlineuarr[$uid]));//1相同账号已经登录,被迫下线
exit;
}
}
}
if ($onlineuarr)
{
foreach ($onlineuarr as $uid => $v) {//清理列表
if ($v+$kicktime<$now)//如果不动作时间>600S
{
unset($onlineuarr[$uid]);//剔除
}
}
}
$this->input->set_cookie('ajaxtime',$now,0);//写入COOKIE 供客户端调用
file_put_contents('./userfiles/time.dat', $now,LOCK_EX);//写入时间文件
if ($onlineuarr)
{
if ($oldarr!=$onlineuarr)
{
file_put_contents('./userfiles/user.dat', serialize($onlineuarr),LOCK_EX);//写入USER文件
}
}else file_put_contents('./userfiles/user.dat', '',LOCK_EX);//写入USER文件
}
}
客户端页面导入JS文件,内容为:
//读取COOKIE
function getCookie(name){
var strCookie=document.cookie;
var arrCookie=strCookie.split("; ");
for(var i=0;i<arrCookie.length;i++){
var arr=arrCookie.split("=");
if(arr==name)return arr;
}
return "";
}
/**
* flush
*/
function uon() {
var spacet=30;//间隔时间
var url=_ServerValue.path.base_url+'index.php/welcome/uon';
var lastime=getCookie('ajaxtime');
if (lastime=="") {
$.get(url, {}, function (data){
if (data!=null) {
KS.showTips('你的账号已经在IP:'+data.ip+'处登录,您被迫下线,如有疑问请联系管理员',1,4);
setTimeout("window.location.reload()", 4000);
}
},'json');
}else{
if (parseInt(lastime)+spacet<_ServerValue.time) {
$.get(url, {}, function (data){
if (data!=null) {
KS.showTips('你的账号已经在IP:'+data.ip+'处登录,您被迫下线,如有疑问请联系管理员',1,5);
setTimeout("window.location.reload()", 5000);
}
},'json');
}
}
setTimeout("uon()",30000);
}
jQuery(function($){
uon();
});
代码应该能看懂,懒得说了.
页:
[1]