cookie跨域:让不一样域下的session cookie有着一样的session idjavascript
session共享:同一会话系统,客户端不一样域下的session id相同故可访问相同的会话状态php
彻底跨域的网站架构和业务分配在平常生活中并很多见,你天天上淘宝去支付宝付款,还有我常常上的大B站,出来个biligame的业务,将原来B站的跨二级域单点登陆提高到了彻底跨域的高度html
=====================================================================java
此协议能够完成cookie的跨域设置,即我在A域下请求B域的某个方法,B域上加载此协议后能够实现经过A域的请求完成cookie设置【固然此cookie的域确定是B域的】,说的简单些就是A域的cookie只能是在A域下设置,再怎样你也作不到在A域下设置一个B域的cookie,但你能够经过A域向B域发送一个跨域请求,B域响应此请求,虽然此请求来至A域,在某些状况下(IE大法)依旧没法完成cookie的设置,但在P3P协议的帮助下,即B域上运行着P3P协议,就能够完美的接收来至任何他域的请求来设置cookie了【再次强调,B域的cookie只能在B域下设置,若A域下就能设置B域的cookie先不说SOP协议固然无存,咱们还没事折腾什么跨域】,门已开,确定得须要安检,这就涉及到B域对外域请求作合法性检查的事情了redis
在A域下不能设置域为B域的cookie,域为X的cookie只能在X域下被设置,但此请求能够经过外域发起,A向B发起,B验证接收相关数据设置域为B的cookie,虽然用户目前尚未浏览B,但本地已经生成了B域的cookie数据库
能够看到在此域下设置的外域的cookie没有"生效",可能有人说当前域只能访问当前域下的cookie,很好,咱们继续看下面的与此cookie对应的域是否能访问到,再没有那就能够证实了,并且此域下经过script标签发起跨域请求跨域
此域运行了p3p协议,响应了来至www.sallency.com的请求,根据传递的参数设置cookie,这样就完成了cookie跨域设置,即我并无访问www.yii.com,但我客户端已经生成一个此域的cookie,是我从www.sallency.com跨域完成生成的服务器
=====================================================================cookie
session共享的根本所在就是要让每一个域下的session_id相同session
二级跨域只须要把session cookie domain设定为一级域,这样每一个二级域都使用此一级域的session cookie做为session id去读取服务器端的会话状态,就实现了单点登陆
彻底跨域则须要跨域设置相同的session cookie
session是存储在服务器端与用户本地的session cookie挂钩的用户对话数据,当咱们每次向服务器发送请求时都会携带本地的cookie,服务端session_start后会检查请求中有无session cookie的键值,有则根据此键值去session系统读取对应的数据载入内存,就造成了$_SESSION超全局变量,若没有则在客户端本地生成域为当前域的session cookie(注意cookie的匹配策略一样为最长匹配,www.sallency.com可访问域为www.sallency.com和.sallency.com的cookie,但会选取最长匹配域做为最后值 )
能够看出相同键值下会作域的最长匹配,这其实也是二级跨域时为何要把服务器的session.cookie_domain设定为父域,不然每次请求服务器session_start时服务器会按session.cookie_domain的域去检测有没有此域的session cookie的键值,有那就是session_id,没有服务器会设置一个当前二级域的session cookie,每次请求的session id就成为此二级域本身从新生成的,那就达不到咱们目的了,咱们的目的是服务器将一级域做为session cookie的域,这样不论哪一个子域都会把域为一级域的session cookie的session_id做为键值去读取服务器端的session
session共享通常是使用数据库模式,共用一个数据库系统做为session系统,我为了方便使用的redis模式,很简单,没什么可讲的
=====================================================================
index.php 主界面
<?php error_reporting(E_ALL); //使用redis作session共享 ini_set('session.save_handler', 'redis'); ini_set('session.save_path', 'tcp://192.168.30.154:6379'); session_start(); //退出 销毁服务器端的session 状态彻底同步 其余站点也会退出登陆 if (isset($_GET['act'])) { session_destroy(); header("location:index.php"); } //添加新的session 用以验证session彻底同步 if (isset($_POST['add'])) { $_SESSION[$_POST['key']] = $_POST['value']; header("location:index.php"); } ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>www.asite.com</title> </head> <body> <?php if (isset($_SESSION['user'])) { ?> <div>welcome!<?php echo $_SESSION['user']?></div> <div> <h4>session彻底同步验证</h4> <?php foreach ($_SESSION as $key => $value): ?> <p><?php echo $key . '--' . $value?></p> <?php endforeach ?> </div> <div> <h4>添加新的session键值</h4> <form action="" method="post"> <input type="text" name="key" placehodler="session key"> <input type="text" name="value" placehodler="session value"> <input type="submit" value="Add" name="add"> </form> </div> <a href="index.php?act=logout">退出</a> <?php } elseif (isset($_POST['submit'])) { //用户登陆 $_SESSION['user'] = $_POST['user']; $_SESSION['passwd'] = $_POST['passwd']; //同时触发cookie跨域设置的请求 header("location:p3p.php"); } else { ?> <div> <h4>登陆<h4> <form action="" method="post"> <input type="text" name="user" placehodler="username"> <input type="text" name="passwd" placehodler="userpasswd"> <input type="submit" value="Login" name="submit"> </form> </div> <?php } ?> </body> </html>
p3p.php 完成跨域cookie设置请求
asite确定是请求bsite设置好和本身session name session id相同的session cookie
<?php header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"'); if (isset($_GET['sessname']) && isset($_GET['sessid'])) { // cross domain request from www.bsite.com setcookie($_GET['sessname'], $_GET['sessid'], time() + 3600, '/', 'www.asite.com'); header("location:index.php"); } ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>asite cross domain set bsite cookie</title> <?php //在这里我没有作session redis共享的一些初始化设置,由于我不并不去读取当前session的数据内容 //我只需把session name 和 session id 跨域请求并传递给bsite,其会根据我传递的参数在其域下设定相同的session cookie session_start(); echo "<script src='http://www.bsite.com/p3p.php?sessid=" . session_id() . "&sessname=". session_name() ."'></script>"; ?> </head> <body> <div style="text-align: center"> <p>success login</p> </div> </body> <script type="text/javascript"> window.onload = function() { setTimeout(function(){ window.location.replace('index.php'); }, 1000); } </script> </html>
=====================================================================
index.php 与asite index.php不一样之处就在于页面title不同...方便识别嘛....
<?php error_reporting(E_ALL); //使用redis作session共享 ini_set('session.save_handler', 'redis'); ini_set('session.save_path', 'tcp://192.168.30.154:6379'); session_start(); //退出 销毁服务器端的session 状态彻底同步 其余站点也会退出登陆 if (isset($_GET['act'])) { session_destroy(); header("location:index.php"); } //添加新的session 用以验证session彻底同步 if (isset($_POST['add'])) { $_SESSION[$_POST['key']] = $_POST['value']; header("location:index.php"); } ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>www.bsite.com</title> </head> <body> <?php if (isset($_SESSION['user'])) { ?> <div>welcome!<?php echo $_SESSION['user']?></div> <div> <h4>session彻底同步验证</h4> <?php foreach ($_SESSION as $key => $value): ?> <p><?php echo $key . '--' . $value?></p> <?php endforeach ?> </div> <div> <h4>添加新的session键值</h4> <form action="" method="post"> <input type="text" name="key" placehodler="session key"> <input type="text" name="value" placehodler="session value"> <input type="submit" value="Add" name="add"> </form> </div> <a href="index.php?act=logout">退出</a> <?php } elseif (isset($_POST['submit'])) { //用户登陆 $_SESSION['user'] = $_POST['user']; $_SESSION['passwd'] = $_POST['passwd']; //同时触发cookie跨域设置的请求 header("location:p3p.php"); } else { ?> <div> <h4>登陆<h4> <form action="" method="post"> <input type="text" name="user" placehodler="username"> <input type="text" name="passwd" placehodler="userpasswd"> <input type="submit" value="Login" name="submit"> </form> </div> <?php } ?> </body> </html>
p3p.php 完成跨域cookie设置请求 bsite确定是请求asite设置好和本身session name session id相同的session cookie
<?php header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"'); if (isset($_GET['sessname']) && isset($_GET['sessid'])) { // cross domain request from www.asite.com setcookie($_GET['sessname'], $_GET['sessid'], time() + 3600, '/', 'www.bsite.com'); header("location:index.php"); } ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>bsite cross domain et asite cookie</title> <?php //在这里我没有作session redis共享的一些初始化设置,由于我不并不去读取当前session的数据内容 //我只需把session name 和 session id 跨域请求并传递给asite,其会根据我传递的参数在其域下设定相同的session cookie session_start(); echo "<script src='http://www.asite.com/p3p.php?sessid=" . session_id() . "&sessname=". session_name() ."'></script>"; ?> </head> <body> <div style="text-align: center"> <p>success login</p> </div> </body> <script type="text/javascript"> window.onload = function() { setTimeout(function(){ window.location.replace('index.php'); }, 1000); } </script> </html>
=====================================================================
效果
能够看到asite和bsite的session cookie的session id是相同的,因此两者会读取服务器上的同一session数据