本篇文章根據個人理解的知識整理彙總,包含 Cookie、Session 的基礎知識和單點登錄的方法,如有不足之處,請大家多多指正。 ...
本篇文章根據個人理解的知識整理彙總,如有不足之處,請大家多多指正。
單點登錄(SSO——Single Sign On)的應用是很普遍的,尤其在大型網站系統中,比如百度,登錄百度賬號和,再轉到百度經驗、百度貼吧等是不用重新登錄的。本文將從 cookie 和 session 基礎詳細介紹單點登錄的原理,代碼實現為 PHP。
Cookie
Cookie 是由客戶端訪問伺服器時伺服器發送給客戶端的特殊信息,且這些信息以文本文件的方式存儲在客戶端。第一次訪問伺服器時,伺服器會在 HTTP 響應頭(Response Header)返回 Cookie 信息。客戶端保存 Cookie 信息之後,下次訪問伺服器時,HTTP請求頭(Request Header)會包含 Cookie 信息。
簡單的說: 伺服器不認識訪問它的客戶端,為了識別它們,就給每個訪問它的客戶端一個口令,伺服器通過口令識別這些客戶端。
註意: 不是訪問每個伺服器都會返回 Cookie 的,只有伺服器中有設置 Cookie ,才會返回給客戶端。
Cookie 生成和傳遞流程
- 在本地伺服器下的 test.php 中設置 Cookie
<?php
// Cookie 是 HTTP 標頭的一部分,因此 setcookie() 函數必須在其它信息被輸出到瀏覽器前調用,這和對 header() 函數的限制類似
setcookie('testCookie', 'this is test cookie');
通過瀏覽器訪問本地伺服器 localhost/test.php,報文如下:
刪除本地伺服器下 test.php 中的 setcookie,再次訪問 localhost/test.php,報文如下:
Cookie 流程圖
簡單登錄示例:
<?php
# 登錄
setcookie('userName', 'test');
# 判斷是否已登錄
if (isset($_COOKIE['userName'])) {
echo '已登錄';
}
關於 Cookie 的具體用法暫時不多說明,本篇文章主要講解機制原理
Session
Session 是伺服器端使用的一種記錄客戶端狀態的機制,使用上比Cookie簡單一些,相應的也增加了伺服器的存儲壓力。在客戶端訪問伺服器時,伺服器會創建 Session 並生成一個 Session id 發到客戶端,客戶端下次訪問時需要帶著 Session id,伺服器則根據 Session id 找到相應的 Session。
Session 生成和傳遞流程
- 伺服器設置 Session:localhost/session.php
<?php
session_start();
$_SESSION['testSession'] = 'This is test';
客戶端瀏覽器訪問伺服器:localhost/session.php,報文如下圖:
客戶端瀏覽器再此訪問伺服器(註釋代碼):localhost/session.php,報文如下:
Cookie 和 Session 的關係圖(接上節中的設置)
單點登錄
在介紹單點登錄的方式之前先介紹一下 PHP 中的 Cookie 中的設置,方便容易理解
bool setcookie ( string $name [, string $value = "" [, int $expire = 0 [, string $path = "" [, string $domain = "" [, bool $secure = false [, bool $httponly = false ]]]]]] )
參數:
- name: Cookie 名稱。
- value: Cookie 值。
- expire: Cookie 的過期時間。
- path: Cookie 有效的伺服器路徑。 設置成 '/' 時,Cookie 對整個功能變數名稱 domain 有效。 如果設置成 '/foo/', Cookie 僅僅對 domain 中 /foo/ 目錄及其子目錄有效(比如 /foo/bar/)。 預設值是設置 Cookie 時的當前目錄。
- domain: Cookie 的有效功能變數名稱/子功能變數名稱。 設置成子功能變數名稱(例如 'www.example.com'),會使 Cookie 對這個子功能變數名稱和它的三級功能變數名稱有效(例如 w2.www.example.com)。 要讓 Cookie 對整個功能變數名稱有效(包括它的全部子功能變數名稱),只要設置成功能變數名稱就可以了(這個例子里是 'example.com')。
由上節我們知道,Session 是存放在伺服器中的,客戶端與伺服器的通信會話是通過 Session id 識別的, 客戶端 Session id 是存放在 cookie 中,因此單點登錄大致分為:同功能變數名稱不同站點登錄、同域不同子域登錄、不同功能變數名稱登錄。
同功能變數名稱不同站點登錄
由 PHP 中的 Cookie 設置說明可以看出,預設下不同站點是共用 Cookie 的除非設置了不同的有效伺服器路徑。如果設置了不同的有效的伺服器路徑怎麼實現共用登錄呢?哈哈哈,那就將有效伺服器路徑設置為預設 '/' 的就好了。
同域不同子域登錄
同樣,由 PHP 中的 Cookie 設置說明可以看出,只要設置 Cookie 的 domain(Cookie 的有效功能變數名稱/子功能變數名稱) 參數就可以了,如下:
由於 PHP 中生成 Session 會自動配置 Cookie,因此我們可以直接在 Session 中設置 Cookie 有效域
one.sso.test/create_session
<?php
session_set_cookie_params(time()+3600, '/', 'sso.test');
session_start();
$_SESSION['test'] = 'This is test';
two.sso.test/get_session
<?php
session_set_cookie_params(time()+3600, '/', 'sso.test');
session_start();
echo $_SESSION['test'];
其中後者是可以獲取到 Session 值的。下邊兩圖分別問以上兩個子功能變數名稱的報文和 Cookie 信息
圖一:
圖二:
由圖可見他們的 Session id 是相同的,因此調用的是伺服器上的同一個 Session。
註意:在 PHP 中,配置 Session 的 Cookie 信息,還可以通過修改 php.ini 文件設置
session.cookie_path = /
session.cookie_domain = '.sso.test'
session.cookie_lifetime = 0
不同功能變數名稱登錄
由於涉及到用戶信息安全問題,因此本文通過流程圖大致說一下基本liu流程,具體操作看實際應用
註意: 上圖中的“返回 Cookie 信息”並不是單獨返回的,而是在“跳轉頁面”的 HTTP 響應頭(Response Header)返回,同樣非同步請求的也是在 JS 調用 www.sso2.com 時在 HTTP 響應頭Response Header 返回。
本文到此結束,後續如果有新的理解會補充上去。