SSO(Single Sign-on) in Action

SSO 是一個非常大的主題,我對這個主題有着深深的感受,自從廣州 UserGroup 的論壇成立以來,無數網友都在嘗試使用開源的 CAS , Kerberos 也提供另外一種方式的 SSO ,即基於 Windows 域的 SSO ,還有就是從 2005 年開始一直興旺不衰的 SAML 。

       如果將這些免費的 SSO 解決方案與商業的 Tivoli 或 Siteminder 或 RSA Secure SSO 產品做對比,差距是存在的。畢竟,商業產品的安全性和用戶體驗都是無與倫比的,我們現在提到的 SSO ,僅僅是 Web SSO ,即 Web-SSO 是體現在客戶端;另外一種 SSO 是桌面 SSO ,例如,只需要作爲 Administrator 登錄一次 windows 2000 ,我便能夠在使用 MSN/QQ 的時候免去登錄的環節 ( 注意,這不是用客戶端軟件的密碼記憶功能 ) ,是一種代理用戶輸入密碼的功能。因此,桌面 SSO 是體現在 OS 級別上。
       今天,當我們提起 SSO 的時候,我們通常是指 Web SSO ,它的主要特點是, SSO 應用之間走 Web 協議 ( 如 HTTP/SSL) ,並且 SSO 都只有一個登錄入口。
       簡單的 SSO 的體系中,會有下面三種角色:
       1 , User (多個)
       2 , Web 應用(多個)
       3 , SSO 認證中心( 1 個)
       雖然 SSO 實現模式千奇百怪,但萬變不離其宗:
l         Web 應用不處理 User 的登錄,否則就是多點登陸了,所有的登錄都在 SSO 認證中心進行。
l         SSO 認證中心通過一些方法來告訴 Web 應用當前訪問用戶究竟是不是張三 / 李四。
l         SSO 認證中心和所有的 Web 應用建立一種信任關係, SSO 認證中心對用戶身份正確性的判斷會通過某種方法告之 Web 應用,而且判斷結果必須被 Web 應用信任。
2. CAS 的基本原理
       CAS(Central Authentication Service) 是 Yale 大學發起的一個開源項目,據統計,大概每 10 個採用開源構建 Web SSO 的 Java 項目,就有 8 個使用 CAS。對這些統計,我雖然不以爲然,但有一點可以肯定的是, CAS 是我認爲最簡單實效,而且足夠安全的 SSO 選擇。
       本節主要分析 CAS 的安全性,以及爲什麼 CAS 被這樣設計,帶着少許密碼學的基礎知識,我希望有助於讀者對 CAS 的協議有更深層次的理解。
2.1 CAS的結構體系
從結構體系看, CAS 包含兩部分:
l         CAS Server
CAS Server 負責完成對用戶的認證工作, CAS Server 需要獨立部署,有不止一種 CAS Server 的實現, Yale CAS Server 和 ESUP CAS Server 都是很不錯的選擇。
CAS Server 會處理用戶名 / 密碼等憑證 (Credentials) ,它可能會到數據庫檢索一條用戶帳號信息,也可能在 XML 文件中檢索用戶密碼,對這種方式, CAS 均提供一種靈活但同一的接口 / 實現分離的方式, CAS 究竟是用何種認證方式,跟 CAS 協議是分離的,也就是,這個認證的實現細節可以自己定製和擴展。
l         CAS Client
CAS Client 負責部署在客戶端(注意,我是指 Web 應用),原則上, CAS Client 的部署意味着,當有對本地 Web 應用的受保護資源的訪問請求,並且需要對請求方進行身份認證, Web 應用不再接受任何的用戶名密碼等類似的 Credentials ,而是重定向到 CAS Server 進行認證。
目前, CAS Client 支持(某些在完善中)非常多的客戶端,包括 Java 、 .Net 、 ISAPI 、 Php 、 Perl 、 uPortal 、 Acegi 、 Ruby 、 VBScript 等客戶端,幾乎可以這樣說, CAS 協議能夠適合任何語言編寫的客戶端應用。
2.2 CAS協議
       剖析協議就像剖析設計模式,有些時候,協議讓人摸不着頭腦。 CAS 的代理模式要相對複雜一些,它引入了一些新的概念,我希望能夠在這裏描述一下其原理,有助於讀者在配置和調試 CAS SSO 有更清晰的思路。
如果沒記錯, CAS 協議應該是由 Drew Mazurek 負責可開發的,從 CAS v1 到現在的 CAS v3 ,整個協議的基礎思想都是基於 Kerberos 的票據方式。
       CAS v1 非常原始,傳送一個用戶名居然是 ”yes\ndavid.turing” 的方式, CAS v2 開始使用了 XML 規範,大大增強了可擴展性, CAS v3 開始使用 AOP 技術,讓 Spring 愛好者可以輕鬆配置 CAS Server 到現有的應用環境中。
CAS 是通過 TGT(Ticket Granting Ticket) 來獲取 ST(Service Ticket) ,通過 ST 來訪問服務,而 CAS 也有對應 TGT , ST 的實體,而且他們在保護 TGT 的方法上雖然有所區別,但是,最終都可以實現這樣一個目的——免去多次登錄的麻煩。
       下面,我們看看 CAS 的基本協議框架:
2.1.1 基礎協議
cas_protocol-1.jpg
                                                 CAS
 基礎模式
       上圖是一個最基礎的 CAS 協議, CAS Client 以 Filter 方式保護 Web 應用的受保護資源,過濾從客戶端過來的每一個 Web 請求,同時, CAS Client 會分析 HTTP 請求中是否包請求 Service Ticket( 上圖中的 Ticket) ,如果沒有,則說明該用戶是沒有經過認證的,於是, CAS Client 會重定向用戶請求到 CASServer ( Step 2 )。 Step 3 是用戶認證過程,如果用戶提供了正確的 Credentials , CAS Server 會產生一個隨機的 Service Ticket ,然後,緩存該 Ticket ,並且重定向用戶到 CAS Client (附帶剛纔產生的 Service Ticket ), Service Ticket 是不可以僞造的,最後, Step 5 和 Step6 是 CAS Client  CAS Server 之間完成了一個對用戶的身份覈實,用 Ticket 查到 Username ,因爲 Ticket 是 CAS Server 產生的,因此,所以 CAS Server 的判斷是毋庸置疑的。
       該協議完成了一個很簡單的任務,就是 User(david.turing) 打開 IE ,直接訪問 helloservice 應用,它被立即重定向到 CAS Server 進行認證, User 可能感覺到瀏覽器在 helloservcie 和 casserver 之間重定向,但 User 是看不到, CAS Client  CAS Server 相互間的 Service Ticket 覈實 (Validation) 過程。當 CASServer 告知 CAS Client 用戶 Service Ticket 對應確鑿身份, CAS Client 纔會對當前 Request 的用戶進行服務。
2.2.2 CAS 如何實現 SSO
       當我們的 Web 時代還處於初級階段的時候, SSO 是通過共享 cookies 來實現,比如,下面三個域名要做 SSO :
如果通過 CAS 來集成這三個應用,那麼,這三個域名都要做一些域名映射,
因爲是同一個域,所以每個站點都能夠共享基於 cas.org 的 cookies 。這種方法原始,不靈活而且有不少安全隱患,已經被拋棄了。
CAS 可以很簡單的實現跨域的 SSO ,因爲,單點被控制在 CAS Server ,用戶最有價值的 TGC-Cookie 只是跟 CAS Server 相關, CAS Server 就只有一個,因此,解決了 cookies 不能跨域的問題。
回到 CAS 的基礎協議圖,當 Step3 完成之後, CAS Server 會向 User 發送一個 Ticket granting cookie (TGC) 給 User 的瀏覽器,這個 Cookie 就類似 Kerberos 的 TGT ,下次當用戶被 Helloservice2 重定向到 CAS Server 的時候, CAS Server 會主動 Get 到這個 TGC cookie ,然後做下面的事情:
1,              如果 User 的持有 TGC 且其還沒失效,那麼就走基礎協議圖的 Step4 ,達到了 SSO 的效果。
2,              如果 TGC 失效,那麼用戶還是要重新認證 ( 走基礎協議圖的 Step3) 。
2.2.2 CAS 的代理模式
       模式 1 已經能夠滿足大部分簡單的 SSO 應用,現在,我們探討一種更復雜的情況,即用戶訪問 helloservice , helloservice 又依賴於 helloservice2 來獲取一些信息,如同:
User à helloservice à helloservice2
這種情況下,假設 helloservice2 也是需要對 User 進行身份驗證才能訪問,那麼,爲了不影響用戶體驗(過多的重定向導致 User 的 IE 窗口不停地 閃動 ) ,CAS 引入了一種 Proxy 認證機制,即 CAS Client 可以代理用戶去訪問其它 Web 應用。
代理的前提是需要 CAS Client 擁有用戶的身份信息 ( 類似憑據 ) 。 與其說之前我們提到的 TGC 是用戶持有對自己身份信息的一種憑據,則這裏的 PGT 就是CAS Client 端持有的對用戶身份信息的一種憑據。憑藉 TGC , User 可以免去輸入密碼以獲取訪問其它服務的 Service Ticket ,所以,這裏,憑藉 PGT , Web 應用可以代理用戶去實現後端的認證,而無需前端用戶的參與。
如下面的 CAS Proxy 圖所示, CAS Client 在基礎協議之上,提供了一個額外的 PGT URL 給 CAS Server, 於是, CAS Server 可以通過 PGT URL 提供一個 PGT 給 CAS Client 
cas_protocol-2.jpg
       
初學者可能會對上圖的 PGT URL 感到迷惑,或者會問,爲什麼要這麼麻煩,要通過一個額外的 URL( 而且是 SSL 的入口 ) 去傳遞 PGT ?如果直接在 Step 6 返回,則連用來做對應關係的 PGTIOU 都可以省掉。 PGTIOU 設計是從安全性考慮的,非常必要, CAS 協議安全性問題我會在後面一節介紹。
於是, CAS Client 拿到了 PGT( PGTIOU-85…..ti2td ) ,這個 PGT 跟 TGC 同樣地關鍵, CAS Client 可以通過 PGT 向後端 Web 應用進行認證。如下圖所示, Proxy 認證與普通的認證其實差別不大, Step1, 2 與基礎模式的 Step 1,2 幾乎一樣,唯一不同的是, Proxy 模式用的是 PGT 而不是 TGC ,是 Proxy Ticket ( PT )而不是 Service Ticket 。
最終的結果是, helloservice2 明白 helloservice 所代理的客戶是 David. Turing 同學,同時,根據本地策略, helloservice2 有義務爲 PGTURL=http://helloservice/proxy 服務 (PGTURL 用於表示一個 Proxy 服務 ) ,於是它傳遞數據給 helloservice 。這樣, helloservice 便完成一個代理者的角色,協助 User 返回他想要的數據。
cas_protocol-3.jpg
   代理認證模式非常有用,它也是 CAS 協議 v2 的一個最大的變化,這種模式非常適合在複雜的業務領域中應用 SSO 。因爲,以前我們實施 SSO 的時候,都是假定以 IE User 爲 SSO 的訪問者,忽視了業務系統作爲 SSO 的訪問者角色。
2.3 CAS安全性
       CAS 的安全性是一個非常重要的 Topic 。 CAS 從 v1 到 v3 ,都很依賴於 SSL ,它假定了這樣一個事實,用戶在一個非常不安全的網絡環境中使用 SSO , Hacker 的 Sniffer 會很容易抓住所有的 Http Traffic ,包括通過 Http 傳送的密碼甚至 Ticket 票據。
2.3.1 TGC/PGT 安全性
       對於一個 CAS 用戶來說,最重要是要保護它的 TGC ,如果 TGC 不慎被 CAS Server 以外的實體獲得, Hacker 能夠找到該 TGC ,然後冒充 CAS 用戶訪問所有授權資源。
       SSO 的安全性問題比普通應用的安全性還要嚴重,因爲 SSO 存在一種門檻效應。以前即使 Hacker 能夠截獲用戶在 Web 應用 A 的密碼,它也未必能知道用戶在 Web 應用 B 的密碼,但 SSO 讓 Hacker 只需要截獲 TGC( 突破了門檻 ) ,即能訪問所有與該用戶相關的所有應用系統。
       PGT 跟 TGC 的角色是一樣的,如果被 Hacker 獲得,後果可想而知。
       從基礎模式可以看出, TGC 是 CAS Server 通過 SSL 方式發送給終端用戶,因此,要截取 TGC 難度非常大,從而確保 CAS 的安全性。
       因此,某些人認爲 CAS 可以不使用 SSL 的想法需要更正一下, CAS 的傳輸安全性僅僅依賴與 SSL 。
       跟 Kerberos 一樣 TGT , TGC 也有自己的存活週期。下面是 CAS 的 web.xml 中,通過 grantingTimeout 來設置 CAS TGC 存活週期的參數,參數默認是 120 分鐘,在合適的範圍內設置最小值,太短,會影響 SSO 體驗,太長,會增加安全性風險。
    <context-param>
        <param-name>edu.yale.its.tp.cas.grantingTimeout</param-name>
        <param-value>7200</param-value>
    </context-param>
TGC 面臨的風險主要並非傳輸竊取。比如你登陸了之後,沒有 Logout ,離開了電腦,別人就可以打開你的瀏覽器,直接訪問你授權訪問的應用 ) ,設置一個 TGC 的有效期,可以減少被別人盜用,或者被 Hacker 入侵你的電腦直接獲取你係統目錄下的 TGC Cookie 。
 
2.3.2 Service Ticket/Proxy Ticket 安全性
       首要明白, Service Ticket 是通過 Http 傳送的,以爲着所網絡中的其他人可以 Sniffer 到其他人的 Ticket 。
CAS 協議從幾個方面讓 Service Ticket 變得更加安全。
l         Service Ticket 只能使用一次。
CAS 協議規定,無論 Service Ticket 驗證是否成功, CAS Server 都會將服務端的緩存中清除該 Ticket ,從而可以確保一個 Service Ticket 被使用兩次。
l         Service Ticket 在一段時間內失效。
假設用戶拿到 Service Ticket 之後,他請求 helloservice 的過程又被中斷了, Service Ticket 就被空置了,事實上,此時, Service Ticket 仍然有效。 CAS 規定 Service Ticket 只能存活一定的時間,然後 CAS Server 會讓它失效。通過在 web.xml 中配置下面的參數,可以讓 Service Ticket 在多少秒內失效。
<context-param>
<param-name>edu.yale.its.tp.cas.serviceTimeout</param-name>
<param-value>300 </param-value>
</context-param>
       該參數在業務應用的條件範圍內,越小越安全。
l         Service Ticket 是基於隨機數生成的。
Service Ticket 必須足夠隨機,如果 Service Ticket 生成規則被猜出(如果你使用了 ST+Helloservice+ 自增序列的方式, Hacker 就可以構造下一個 Ticket ), Hacker 就等於繞過 CAS 認證,直接訪問所有服務。
 
3. CAS 以外的其他開源 SSO 方案
       除了 CAS 之外,還有很多開源的 SSO 方案,採用何種方案跟用戶的應用環境有比較大的關係。 SSO 的優劣一般要考慮易用性,安全性,性能,擴展性等因素。
3.1 JOSSO
       經常聽到別人討論 JOSSO  JOSSO ( www.josso.org )是我很早就用過的 SSO 開源項目,我後來拋棄了它,因爲它存在比較多缺點,下面我們來看看:
1, 沒有將後臺認證與 SSO 分離,過分強調 JAAS , Axis 等
JOSSO 官方網站發佈了 JOSSO 三個基準:
Standard Based
  • JOSSO security infrastructure is based on JAAS (Java Authentication and Authorization Service)
  • JOSSO uses web services implementing Axis as the distributed infrastructure.
  • JOSSO uses Struts and JSP standards
這些標準可以看到 JOSSO 的適應性存在較大的限制,因爲 SSO 其實並不關心認證細節,作爲一個開源項目,不應該引用過多的技術,如 Axis ,因爲這個世界還有很多人用 Xfire 。
2, 沒有描述 SSO 協議的 UseCase 圖
 JOSSO 的網站,似乎都看不到一個 SSO 的 UseCase ,容易讓那些關注安全性的大型項目負責人感到憂慮。
3, 缺乏廣泛的 SSO 客戶端支持
JOSSO 的支持的客戶端比較少,這個跟他的 Memember Team 、 Contributor Team 有比較大的關係。
4, 缺乏成功案例
讀者使用任何 SSO 開源方案之前,有必要先了解次方案的成功案例, CAS 全球有 50 多個大學在使用 ( 大學對 SSO 的要求往往更復雜 ) 成功案例,這方面,JOSSO  CAS 存在很大的差距。
5, 不支持跨域的落後設計
當然, JOSSO 不支持跨域是因爲它使用了共享 cookie ,下面的話截取於 JOSSO 的官方文檔:
JOSSO uses a session HTTP cookie to keep track of the SSO session identifier. This cookie lives as long as the browser window is open, being sent only in requests associated with the domain that generated it. This means that all JOSSO partner applications must be accessed using the same domain.
這段話給我們一個提示,如果設計 SSO 的時候,使用了 cookie 來在 SSO Server 和 SSO Agent( 相當於 CAS  CAS Client) 之間共享用戶信息,那麼這個協議是無法突破跨域限制的。因爲當多個 SSO Agent 如果不使用同一個域名,也就是 Microsoft.com 和 IBM.com 無法共享同一個 cookie , JOSSO 採用了一種 DNS 技巧,即使用 Microsoft.sso.com 和 ibm.sso.com 來共享 cookie ,但這帶來的問題同樣很多,尤其是業務系統本身存在一些對域名限制的業務邏輯的時候,需要改動原來業務系統,這不是一件好受的事情。
 
3.2 CoSign
       CoSign 原先是 Michigan 大學的一個 SSO 項目, CoSign 是一個很不錯的設計,但是它跟 CAS 比較相似,都是基於 Kerberos 方式的協議,一個最大的不同是 CoSign 的 SSO Server 是基於 CGI(Java Fans 更多會選擇 CAS) ,對 C/C++ 的羣體應該是一個不錯的選擇。 CoSign 協議的 UseCase 跟 CAS 很相似, CoSign 的客戶端雖然也支持 J2EE/Apache/MSAPI(IIS) ,但它的 Server 端使用 C 來編寫,影響了在 Java 羣體中的使用。 CoSign 是一個不錯的選擇,可能是因爲本人比較喜歡 Kerberos Model 的原因吧。
3.3 WebAuth
       WebAuth 是一種早期的 SSO 方案,它的 WebServer 是用 perl 來編寫的,客戶端支持 Apache , C++ , Perl 等,當然, WebAuth 推出的時候, Java 並不是很流行,現在,要讓 WebAuth 跟衆多的 Java 產品結合不是一件容易的事情。
WebAuth 的協議適用了 Share Secret ,即 SSO Server 和 SSO Client 之間存在一個對稱密鑰 (symmetric key ) 。 SSO Server 和 SSO Client 之間的信任關係通過這個 Key 來保障。
webauth_protocol-4.jpg

   上圖中展示了一個 WebAuth 的基本模式, Client 就是瀏覽器用戶, Generic Web Service 是 SSO Client , WebAuth Service 和 Auth Service 可以看作是 SSO Server


發佈了2 篇原創文章 · 獲贊 4 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章