SSO是在多個應用系統中,使用者只需要登入一次就可以存取所有互信的應用系統。那麼在PHP中要如何實現SSO單一登入呢?以下這篇文章給大家詳細介紹一下單一登入SSO的實作方式。
SSO( Single Sign On ),即單點登錄,是一種控制多個相關但彼此獨立的系統的訪問權限, 擁有這一權限的用戶可以使用單一的ID和密碼存取某個或多個系統從而避免使用不同的使用者名稱或密碼,或透過某種配置無縫地登入每個系統。
對於大型系統來說使用單一登入可以減少使用者很多的麻煩。就拿百度來說吧,百度下面有很多的子系統——百度經驗、百度知道、百度文庫等等,如果我們使用這些系統的時候,每一個系統都需要我們輸入用戶名和密碼登入一次的話,我相信使用者體驗一定會直線下降。
與 SSO 互動的2個元素:1. 用戶,2. 系統,它的特點是:一次登錄,全部訪問。 SSO 是存取控制的一種,控制使用者能否登錄,即驗證使用者身份,而且是所有其它系統的身份驗證都在它這裡進行,從整個系統層面來看SSO ,它的核心就是這3個元素了:1. 用戶,2. 系統,3. 驗證中心。
假如我們的網站是依照下面的網域部署的:
這兩個網站共用相同網域onmpw.com 。
預設情況下,瀏覽器會傳送 cookie 所屬的網域對應的主機。也就是說,來自於 sub1.onmpw.com 的 cookie 預設所屬的網域是 .sub1.onmpw.com 。因此,sub2.onmpw.com 不會得到任何的屬於 sub1.onmpw.com 的 cookie 資訊。因為它們是在不同的主機上面,而二者的子域也是不同的。
setcookie(‘token’, ’xxx’, '/', ’.onmpw.com’);复制代码
造訪 sub2.onmpw.com 系統,瀏覽器會將 cookie 中的信息 token 附帶在請求中一塊兒發送到 sub2.onmpw.com 系統。這時該系統會先檢查 session 是否登錄,如果沒有登入則驗證 cookie 中的 token 從而實現自動登入。
sub2.onmpw.com 登入成功以後再寫 session 訊息。以後的驗證就用自己的 session 資訊驗證就可以了。
這裡存在一個問題就是sub1 系統退出以後,除了可以清除自身的session 資訊和所屬域為.onmpw .com 的cookie 的資訊。它並不能清除 sub2 系統的 session 資訊。那 sub2 仍然是登入狀態。也就是說,這種方式雖說可以實現單一登錄,但是不能實現同時退出。原因是,sub1 和sub2 雖說透過setcookie 函數的設定可以共用cookie,但是二者的sessionId 是不同的,而且這個sessionId 在瀏覽器中也是以cookie 的形式儲存的,不過它所屬的網域並不是.onmpw. com 。
那要如何解決這個問題呢?我們知道,對於這種情況,只要是兩個系統的 sessionId 相同就可以解決這個問題了。也就是說存放 sessionId 的 cookie 所屬的網域也是 .onmpw.com 。在PHP中,sessionId 是在 session_start() 呼叫以後產生的。要使sub1 和sub2 有共同的sessionId ,那必須在session_start() 之前設定sessionId 所屬域:
ini_set('session.cookie_path', '/'); ini_set('session.cookie_domain', '.onmpw.com'); ini_set('session.cookie_lifetime', '0');复制代码
- 1、經過上面的步驟就可以實現不同二級域名的單一登入與登出。
- 2、不過還可以再簡化,如確保 sessionId 相同就可以實現不同二級網域的單一登入與登出。
- 參考文章: https://www.onmpw.com/tm/xwzj/network_145.html
假設我們需要在以下這些站之間實作單一登入
上面的方案就行不通了。
目前github 上有開源的SSO 解決方案,實作原理與主流SSO 差不多:https://github.com/jasny/sso
核心原理:
同根網域不指定domain 根域名,第一次授權需要每次都要跳到授權服務,但是指定了domain, 同根網域只要有一個授權成功,都可以共用那個cookie 了,下次就不用再授權了,直接就可以請求使用者資訊了。
第一次造訪A:
#第二次存取B:
使用者到認證中心登入後,使用者和認證中心之間建立起了會話,我們把這個會話稱為全域會話。當使用者後續存取系統應用程式時,我們不可能每次應用程式請求都到認證中心去判定是否登錄,這樣效率非常低下,這也是單網頁應用程式不需要考慮的。
我們可以在系統應用程式和使用者瀏覽器之間建立起局部會話,局部會話保持了客戶端與該系統應用的登入狀態,局部會話依附於全域會話存在,全域會話消失,局部會話必須消失。
使用者存取應用程式時,先判斷局部會話是否存在,如存在,即認為是登入狀態,無需再到認證中心去判斷。如不存在,就重定向到認證中心判斷全域會話是否存在,如存在,通知該應用,該應用程式與客戶端就建立起它們之間局部會話,下次請求該應用,就不去認證中心驗證了。
使用者在一個系統退出了,存取其它子系統,也應該是退出狀態。要做到這一點,應用程式除結束本地局部會話外,還應該通知認證中心該使用者退出。
認證中心接獲退出通知,即可結束全域會話,使用者存取其它應用程式時,都顯示已登出狀態。
需要不需要立即通知所有已建立局部會話的子系統,將它們的局部會話銷毀,可根據實際項目來。
推薦學習:《PHP影片教學》
以上是深入淺析PHP中實作SSO單一登入的方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!