首頁  >  文章  >  後端開發  >  深入淺析PHP中實作SSO單一登入的方法

深入淺析PHP中實作SSO單一登入的方法

青灯夜游
青灯夜游轉載
2021-07-09 19:15:344732瀏覽

SSO是在多個應用系統中,使用者只需要登入一次就可以存取所有互信的應用系統。那麼在PHP中要如何實現SSO單一登入呢?以下這篇文章給大家詳細介紹一下單一登入SSO的實作方式。

深入淺析PHP中實作SSO單一登入的方法

SSO( Single Sign On ),即單點登錄,是一種控制多個相關但彼此獨立的系統的訪問權限, 擁有這一權限的用戶可以使用單一的ID和密碼存取某個或多個系統從而避免使用不同的使用者名稱或密碼,或透過某種配置無縫地登入每個系統。

對於大型系統來說使用單一登入可以減少使用者很多的麻煩。就拿百度來說吧,百度下面有很多的子系統——百度經驗、百度知道、百度文庫等等,如果我們使用這些系統的時候,每一個系統都需要我們輸入用戶名和密碼登入一次的話,我相信使用者體驗一定會直線下降。

與 SSO 互動的2個元素:1.  用戶,2. 系統,它的特點是:一次登錄,全部訪問。 SSO 是存取控制的一種,控制使用者能否登錄,即驗證使用者身份,而且是所有其它系統的身份驗證都在它這裡進行,從整個系統層面來看SSO ,它的核心就是這3個元素了:1. 用戶,2. 系統,3. 驗證中心。

深入淺析PHP中實作SSO單一登入的方法

1、同一個網域但不同的子網域如何進行單一登入

假如我們的網站是依照下面的網域部署的:

  • sub1.onmpw.com
  • sub2.onmpw.com

這兩個網站共用相同網域onmpw.com 。

預設情況下,瀏覽器會傳送 cookie 所屬的網域對應的主機。也就是說,來自於 sub1.onmpw.com 的 cookie 預設所屬的網域是 .sub1.onmpw.com 。因此,sub2.onmpw.com 不會得到任何的屬於 sub1.onmpw.com 的 cookie 資訊。因為它們是在不同的主機上面,而二者的子域也是不同的。

1.1 設定二者的cookie 資訊在同一個網域下

  • 登入sub1.onmpw.com 系統
  • 登入成功以後,產生唯一識別碼Token(知道token,就知道哪個使用者登入了)。設定 cookie 信息,這裡需要注意,將Token存到 cookie 中,但是在設定的時候必須將這 cookie 的所屬域設定為頂級域 .onmpw.com 。這裡可以使用 setcookie 函數,該函數的第四個參數是用來設定 cookie 所述域的。
setcookie(‘token’, ’xxx’, '/', ’.onmpw.com’);复制代码
  • 造訪 sub2.onmpw.com 系統,瀏覽器會將 cookie 中的信息 token 附帶在請求中一塊兒發送到 sub2.onmpw.com 系統。這時該系統會先檢查 session 是否登錄,如果沒有登入則驗證 cookie 中的 token 從而實現自動登入。

  • sub2.onmpw.com 登入成功以後再寫 session 訊息。以後的驗證就用自己的 session 資訊驗證就可以了。

1.2 退出登入

這裡存在一個問題就是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

2、不同網域之間如何實作單點登入- CAS

假設我們需要在以下這些站之間實作單一登入

  • #www.onmpw1.com
  • www.onmpw2. com
  • www.onmpw3.com

上面的方案就行不通了。

目前github 上有開源的SSO 解決方案,實作原理與主流SSO 差不多:https://github.com/jasny/sso

核心原理:

  • 1、客戶端存取不同的子系統,子系統對應的 SSO 使用者服務中心使用相同的 SessionId
  • 2、子系統Broker 與Server 間透過attach 進行了授權連結綁定

同根網域不指定domain 根域名,第一次授權需要每次都要跳到授權服務,但是指定了domain, 同根網域只要有一個授權成功,都可以共用那個cookie 了,下次就不用再授權了,直接就可以請求使用者資訊了。

第一次造訪A:

深入淺析PHP中實作SSO單一登入的方法

#第二次存取B:

深入淺析PHP中實作SSO單一登入的方法

2.1 登入狀態判斷

使用者到認證中心登入後,使用者和認證中心之間建立起了會話,我們把這個會話稱為全域會話。當使用者後續存取系統應用程式時,我們不可能每次應用程式請求都到認證中心去判定是否登錄,這樣效率非常低下,這也是單網頁應用程式不需要考慮的。

我們可以在系統應用程式和使用者瀏覽器之間建立起局部會話,局部會話保持了客戶端與該系統應用的登入狀態,局部會話依附於全域會話存在,全域會話消失,局部會話必須消失。

使用者存取應用程式時,先判斷局部會話是否存在,如存在,即認為是登入狀態,無需再到認證中心去判斷。如不存在,就重定向到認證中心判斷全域會話是否存在,如存在,通知該應用,該應用程式與客戶端就建立起它們之間局部會話,下次請求該應用,就不去認證中心驗證了。

2.2 退出

使用者在一個系統退出了,存取其它子系統,也應該是退出狀態。要做到這一點,應用程式除結束本地局部會話外,還應該通知認證中心該使用者退出。

認證中心接獲退出通知,即可結束全域會話,使用者存取其它應用程式時,都顯示已登出狀態。

需要不需要立即通知所有已建立局部會話的子系統,將它們的局部會話銷毀,可根據實際項目來。

推薦學習:《PHP影片教學

以上是深入淺析PHP中實作SSO單一登入的方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除