前面作了一个新项目,须要用户资源能够须要共享。因为以前没有作过这样的东西,回家以后,立马网站百度“单点登陆”。帖子不少,甄别以后,这里列几篇认为比较有养分。javascript
http://blog.csdn.net/ghsau/article/details/20545513,http://blog.sina.com.cn/s/blog_5f66526e0102vf43.htmlphp
若是要解决两个网站之间的同步登陆(单点登陆)问题,首先来看看一个网站的登陆问题。html
不少人知道一个网站的登陆问题,PHP不就是把经过$_SESSION['user']=array('username'=>'user1');那么,看看php的一句代码,作了那些操做。以windows下wamp环境配合php的配置文件php.ini看瞧瞧session的相关知识?java
php中默认提供session处理方案,能够在php.ini配置文件中看到有这么两行,ajax
session.save_handler=fileredis
session.save_path = "E:/wamp/tmp",以下图json
这两句告诉咱们,在php中session的处理是文件files的方式,存储的地方是E:/wamp/tmp,看看个人文件目录下去windows
好啦,这就是传说中的session,看得着,点得鸟。能够用记事本打开下,能够看到是一些字符,这是php对象数组序列化以后的字符串。就是把session对象序列化以后,写到文件中,达到session的持久化。若是采用默认配置的话,多个网站的session文件都是存在一个地方的。也就是说,若是同一台服务器中,有两个网站,网站a和网站b的session文件都会存储在一个地方,session文件都有本身的惟一标示符,sessionID。sessionID的生成,sessionID是惟一的,这个sessionID跟session的持久化文件名称是对应的。php经过sessionID去获取session文件,反序列化出来,就能达到session读取的功能了。这样的话,会不会想到,若是两个sessionID相同的话,用户在网站a登陆了,用户在去访问网站b的时候,若是sessionID相同,就是已经的登陆的状态了。数组
解决:两个网站sessionID相同思路浏览器
php提供了session_id()这个函数能够获取到sessionID,能够设置sessionID。在原生PHP中,能实现经过session_id()去修改sessionID,在一些框架中比较难实现,须要深究框架代码,为什么难实现呢,这里要了解session_id()和session_start()一些关联了,须要先设定sessionID以后,再去session_start()。因此在框架中,会自动的启用session_start(),因此在启动以后再去修改,sessionID未被修改。
sessionID相同的还有一种方式,就是浏览器修改sessionID,sessionID是存储在cookie中,在配置文件中,能够看到session.name = PHPSESSID,那么这个PHPSESSID就是sessionID在cookie中的name了。以下图
浏览器和服务器之间每次交互,这个cookie值都会传递给服务器,因此若是咱们前台去修改这个值的话,就可让两个网站公用一个sessionID的值了。
具体实施:在网站b全部的页面用户加载的时候,去请求网站a的一个接口,看看用户是否有登陆,若是有的话,就放回sessionID给网站b,网站b接受到sessionID以后,就修改浏览器cookie中的PHPSESSID值。这样网站b的用户再去操做的话,就会发现本身sessionID对应的session文件跟网站a是同一个,从而达到同步登陆。
网站b代码须要作的就是页面每次访问都须要去请求a网站的数据判断用户是否在a网站登陆。
<if condition="!session('?member')"> <!--未登陆--> <script type="text/javascript"> function setCookie(name,value) { document.cookie = name + "="+ escape (value)+";path=/"; } //jsonp登陆函数 function jsonp_do(data) { //log(''); } <{~$t=time()}> $(document).ready(function(){ $.ajax({ type:'get', url:"<{:C('SSO_Site')}>?_ts=<{$t}>&_token=<{:md5($t.C('SecretKey'))}>", dataType:'jsonp', crossDomain: true, jsonp: "callback", jsonpCallback:'jsonp_do', success:function(data){ if(data.error==0){ setCookie('PHPSESSID',data.sess_id); } }, error: function(XHR, textStatus, errorThrown){ //log } }); }); </script> </if>
那么网站a就要给出对应的页面来给网站b请求且返回数据。
/** * [index 用户登陆] * @Author:wty * @DateTime:2016年12月12日11:22:02 * @return [type] [description] */ public function index() { //能够适当加入用户ip做为加密因子和浏览器因数 $token=I('get._token');//加密串 $timespan=I('get._ts');//时间时间戳 $referer=$_SERVER['HTTP_REFERER'];//这里能够限定安全网址 $error=100; //这里须要配置 $allow=C('Allow_Site'); if(in_array($referer,$allow)){//若是是在容许访问列表里面 $error=1; if($token&&$timespan){ $error=2; $secretKey=C('SecretKey');//秘钥 $check=md5($timespan.$secretKey); if($check==$token){ $error=3; if(session('?member')){ $error=0; $return=array('error'=>0,'username'=>session('member.username'),'sess_id'=>session_id()); echo 'jsonp_do('.json_encode($return).')'; exit; } } } } echo 'jsonp_do('.json_encode(array('error'=>$error)).')'; }
如今多数网站都会采用到负载均衡多服务器,若是是多服务器的话,session的存储能够考虑的memcached或者redis中,上面说道php对于session的默认存储方式是files,若是用memcached的话,就要修改配置文件php.ini
session.save_handler=memcached
session.save_path = "tpc://192.168.1.1"
在save_handler=memcached或者memcache这里,有点区别,若是配置写的是memcached的话,下面的save_path就要写tcp://192.168.1.1:11211,若是是memcache的话,save_path就要填写为192.168.1.1:11211
差异不大。
至此简单版本的单点登陆基本完成了。
更多原创博客请看我的独立博客:传送门