PHP+ajax+P3P实现多域名跨域登录
- 5119
- PHP
- 8
- super_dodo
- 2016/09/18
近期有一种想法和尝试,需要实现A域名用户与B域名用户的同步登录;
该同步登陆需求需满足以下三个关键点:
1.A域名下登陆的用户,跳转到B域名下时实现同步登陆;
2.B域名下点击A域名下的退出链接,实现A域名与B域名的同时退出
3.用户直接访问B域名时,可以自动判断A域名下是否存在用户登录,如果存在,则实现B域名下的用户同步登陆。
首先解决跨域的同步登陆登出,有以下可行的解决思路:
1.两个域共享SESSION服务器,即统一的内存服务器,这样两个域下的SESSIONID会相同,会自动无缝实现同步登陆登出;但该解决方案需要额外的硬件投入,并且需要懂这方面部署的技术人员
2.通过url传递sessionid
3.通过P3P协议获取跨域的SESSION
为解决该需求,我经过查询各种资料,并拟定了自己的一套解决方案,分享给大家,其要点如下:
1.当用户在A域名下登录后,访问A域名下网站时,会ajax请求B域下的js脚本文件,写入B域COOKIE及SESSION,实现B域下登录;
2.当用户在A域名下退出后,访问A域名下网站时,会ajax请求B域下的js脚本文件(同登录参数不同.,清除B域COOKIE及SESSION,实现B域下登出;
3.当用户直接访问B域网页时,请求A域下脚本,判断A域下是否存在登录,如果存在,则将COOKIE及SESSION赋值到当前域的网页中,通过ajax实现当前域
COOKIE及SESSION的写入。
我将dodobook.net设定为A域名;dodobook.me设定为B域名。
以下是相关代码:
############# dodobook.net ApiController.php ################# /* * 根据当前域(dodobook.net的cookie信息设置dodobook.me域下的cookie及session * 如果为空,则清空处理 * */ function setckAction() { $clr = $this->_request->getParam("clr"); $dodobook_me_user = ($clr) ? '' : urlencode($_COOKIE['dodobook_me_LOGGED_USER']); $this->view->assign("dodobook_me_user",$dodobook_me_user); } /* * 提供给dodobook.me域下,获取当前域(dodobook.net.的cookie及session * 以脚本变量返回给dodobook.me浏览器端 * */ function getckAction() { header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"'); echo 'var ck="'.$_COOKIE['dodobook_me_LOGGED_USER'].'";'; echo 'var sess="'.$_SESSION['user']['uid'].'";'; exit(); } ############# dodobook.net index.php ################# ##### 默认指定index.php为登录返回的页面 <script src="http://www.dodobook.me/api/setck?dodobook_me_user={$dodobook_me_user}"></script> ############# dodobook.me api.php ################# /* * 显示dodobook.net域下的cookie及SESSION * 赋值到js变量 * js 通过ajax写入cookie和session:如果dodobook.net已退出,则dodobook.me做退出处理 * */ function getdodobook_meck() { include $this->template->getfile('api/getdodobook_meck'); } /* * dodobook.net域下设置dodobook.me域下的cookie及session * 如果为空,则清空处理 * */ function setck() { header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"'); $dodobook_me_user = trim($_GET['dodobook_me_user']); if(!empty($dodobook_me_user)) { setcookie("dodobook_me_LOGGED_USER", urldecode($dodobook_me_user), time()+3600*24*365, "/", ".dodobook.me"); $this->cookieLoginLocal(urldecode($dodobook_me_user)); } else { setcookie("dodobook_me_LOGGED_USER", $dodobook_me_user, '-1', "/", ".dodobook.me"); unset($_SESSION['uid']); } } function setsession() { $dodobook_me_user = trim($_POST['dodobook_me_user']); if(!empty($dodobook_me_user) && empty($_SESSION['uid'])) { setcookie("dodobook_me_LOGGED_USER", urldecode($dodobook_me_user), time()+3600*24*365, "/", ".dodobook.me"); $this->cookieLoginLocal(urldecode($dodobook_me_user)); } else { echo 'uuunset'; setcookie("dodobook_me_LOGGED_USER", $dodobook_me_user, '-1', "/", ".dodobook.me"); //unset($_SESSION['uid']); } } function cookieLoginLocal($cookieId){ $cookieId = explode( '.', base64_decode($cookieId) ); if ($cookieId[0] !== 'baitianshi' || empty($cookieId[1])) { return false; } else { return $this->loginLocal($cookieId[1],false,1); } } function loginLocal($uid,$password=false,$isuid=0) { $_SESSION['uid'] = $uid; return 1; } ############# dodobook.me getdodobook_meck.html ################# <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title>同步登陆</title> <script src="http://p.dodobook.me/js/jquery-1.8.1.min.js" type="text/javascript"></script> <script src="http://www.dodobook.net/api/getck"></script> <script language="javascript"> function setck(dodobook_me_user) { $.post("/api/setsession",{dodobook_me_user:dodobook_me_user},function(re){ });} setck(ck); </script> </head> <body> </body> </html>
该方案尚存在的不足:
当用户直接访问B域时,需要加载一次该页面后,才能判断是否在A域登录,并写入当前域(B域.的SESSION)
原文地址:http://www.yuanrufeng.cn/post/247
相关阅读
- 通过Google API客户端访问Google Play帐户报告PHP库
- PHP执行文件的压缩和解压缩方法
- 消息中间件MQ与RabbitMQ面试题
- 如何搭建一个拖垮公司的技术架构?
- Yii2中ElasticSearch的使用示例
热门文章
- 通过Google API客户端访问Google Play帐户报告PHP库
- PHP执行文件的压缩和解压缩方法
- 消息中间件MQ与RabbitMQ面试题
- 如何搭建一个拖垮公司的技术架构?
- Yii2中ElasticSearch的使用示例
最新文章
- 通过Google API客户端访问Google Play帐户报告PHP库
- PHP执行文件的压缩和解压缩方法
- 消息中间件MQ与RabbitMQ面试题
- 如何搭建一个拖垮公司的技术架构?
- Yii2中ElasticSearch的使用示例