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數據