用户
 找回密码
 入住 CI 中国社区
搜索
查看: 1950|回复: 4
收起左侧

[讨论/交流] 求助CI框架下的单点登陆实现

[复制链接]
发表于 2018-6-20 21:50:01 | 显示全部楼层 |阅读模式
研究了好多天了,网上参考了很多资料,做了一些demo,还是不能真正的实现,求谁又经验的给予帮助,回帖讨论,或者加QQ交流
发表于 2018-6-21 08:59:54 | 显示全部楼层
本帖最后由 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>

这个scriptsrc呢,作用主要就是生成def.com域名下的登录cookie,让def.com域名实现与abc.com同步登录,当然上面的script也可以换成iframe

如果login.abc.com页面是ajax登录,那么上面的scriptsrc可以在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就可以了

也许还有其他方法,有请楼下跟帖

 楼主| 发表于 2018-6-21 11:08:43 | 显示全部楼层
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分钟自动退出的规则已经变成退出状态。

这两个域直接的状态如何保持同步呢?  
发表于 2018-6-22 08:41:47 | 显示全部楼层
badapple0412 发表于 2018-6-21 11:08
谢谢,这个方式,虽然我还没有实践,但是看你说明的逻辑,针对用户主动登陆/退出(用户点击登陆或者点击 ...

如果不是硬性要求的话,每个站点都设置cookie有效期为10分钟就好了。
如果要求每个站点都共同受限于这个10分钟的话,可以缓存下来
(可以使用文件缓存,memcache等等,或者存数据库),登录站点,
登录成功后,更新该用户的自动登出的时间为当前时间+10分钟,
并设置各站点的登录cookie为关闭浏览器失效。
各个站点判断是否登录的逻辑里,如果还是登录状态,
并且在自动登出的时间范围内,则更新该用户的自动登出的时间为当前时间+10分钟,反之跳转到登录页。

这样应该能够达到你的要求
发表于 2018-6-22 11:17:24 | 显示全部楼层
给你贴点代码,自己研究下服务器端代码,位置在 index.php/welcome/uon
PHP复制代码
 
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[uid]: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][0])
{
    $onlineuarr[$uid][1]=$now;
}else{
    $this->ion_auth->logout();
echo json_encode(array('ip'=>$onlineuarr[$uid][0]));//1相同账号已经登录,被迫下线
exit;
}
}
 
}
 
if ($onlineuarr)
{
        foreach ($onlineuarr as $uid => $v) {//清理列表
        if ($v[1]+$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文件,内容为:
JS复制代码
 
//读取COOKIE
function getCookie(name){
var strCookie=document.cookie;
var arrCookie=strCookie.split("; ");
for(var i=0;i<arrCookie.length;i++){
var arr=arrCookie[i].split("=");
if(arr[0]==name)return arr[1];
}
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();
});
 
 
复制代码


代码应该能看懂,懒得说了.

本版积分规则