本文分兩部分
1.轉(zhuǎn)他人的文章,詳細(xì)介紹了跨站單點登錄的原理和解決方案
2.我自己寫代碼,著重介紹里面的重點部分
1:
假設(shè)我們需要在以下這些站之間實現(xiàn)單點登錄
www.onmpw1.com
www.onmpw2.com
www.onmpw3.com
對于這種情況,我們有兩種實現(xiàn)方式,其中我們先來介紹實現(xiàn)比較簡單的方式。
方式一
為了實現(xiàn)單點登錄,當(dāng)用戶登錄其中的任何一個站點時,我們需要針對其他每個站點在瀏覽器端設(shè)置cookie信息。
如果用戶在onmpw1站點進行登錄,登錄成功授權(quán)以后,瀏覽器將會存儲一份兒onmpw1站點的cookie信息。同時,為了可以登錄onmpw2和onmpw3,我們需要在設(shè)置onmpw1的cookie的同事也對onmpw2和onmpw3進行cookie設(shè)置。因此在對onmpw1進行響應(yīng)之前,我們需要先跳轉(zhuǎn)到onmpw2和onmpw3站點去設(shè)置cookie信息。

下圖是對于兩個站點的單點登錄模型(三個的圖畫起來比較麻煩,為了節(jié)省時間,就用兩個來表示,但是原理是相同的)

此種情況的驗證步驟是這樣的:
一、用戶向www.onmpw1.com(以下簡稱onmpw1)請求一個需要驗證的頁面。
[狀態(tài): 瀏覽器還沒有驗證的cookie信息]
二、瀏覽器向onmpw1發(fā)送請求(該請求沒有cookie信息,因為它還沒有存儲所屬域為onmpw1.com的cookie信息)。
[狀態(tài): 瀏覽器還沒有驗證的cookie信息]
三、onmpw1發(fā)現(xiàn)在請求中沒有帶cookie信息,所以它將請求重定向到登錄頁面
[狀態(tài): 瀏覽器還沒有驗證的cookie信息]
四、用戶提交了登錄所需驗證的信息并且點擊登錄按鈕,瀏覽器發(fā)送一個post請求到onmpw1。
[狀態(tài): 瀏覽器還沒有驗證的cookie信息]
五、onmpw1收到提交的驗證信息,開始驗證這些信息。如果驗證成功,則標(biāo)記該用戶已經(jīng)登錄。然后會創(chuàng)建帶有登錄用戶信息的cookie,并將其加入響應(yīng)信息中。
[狀態(tài): 瀏覽器還沒有驗證的cookie信息]
六、onmpw1暫時還不去響應(yīng)瀏覽器的請求。這時它將會向瀏覽器發(fā)送重定向到www.onmpw2.com(以下簡稱onmpw2)的命令,并且還帶有在onmpw2站點需要返回的url地址,該地址為最初onmpw1中的。因為cookie信息已經(jīng)在響應(yīng)信息中,所以這個cookie也被發(fā)送給瀏覽器了。
[狀態(tài): 瀏覽器還沒有驗證的cookie信息]
七、瀏覽器接收道帶有驗證的cookie信息和重定向到onmpw2的命令的響應(yīng)信息以后,將cookie信息的域設(shè)置為onmpw2存儲到本地,并且想onmpw2發(fā)送請求。這個請求中會帶有剛才的cookie信息。
[狀態(tài):瀏覽器中已經(jīng)有所屬域為onmpw2的cookie信息]
八、onmpw2立刻會重定向到需要返回的url地址,并且通過讀取瀏覽器發(fā)送的cookie信息,獲取到onmpw1的cookie。并將這cookie也一同發(fā)送給瀏覽器。
[狀態(tài):瀏覽器中已經(jīng)有所屬域為onmpw2的cookie信息]
九、瀏覽器在接受到這些信息以后,會將所屬域為onmpw1的cookie存儲在本地。并且再次向onmpw1發(fā)送一個帶有cookie信息的請求。
[狀態(tài):瀏覽器中已經(jīng)有所屬域為onmpw2和onmpw1的cookie信息]
十、onmpw1接收到驗證信息以后,知道驗證cookie已經(jīng)設(shè)置成功。此時onmpw1會返回相應(yīng)的請求界面,而不再是登錄界面。
[狀態(tài):瀏覽器中已經(jīng)有所屬域為onmpw2和onmpw1的cookie信息]
所以說,當(dāng)用戶再次訪問onmpw2的時候,cookie信息已經(jīng)存儲到瀏覽器中了。這時onmpw2會在cookie中讀取到登錄的用戶的信息,然后提供相應(yīng)的界面給瀏覽器。
這樣,單點登錄就已經(jīng)設(shè)置成功了。在本例中,按照上述步驟,登錄onmpw1以后,onmpw2和onmpw3就可以同時實現(xiàn)登錄了。
如何退出登錄
既然我們已經(jīng)實現(xiàn)了單點登錄,但是我們還得考慮退出的問題。既然是同時登錄的,那總不能在退出的時候一個一個的退出吧!所以說我們還要設(shè)置單點退出。
要想實現(xiàn)單點退出,在本例中,我們需要做的是當(dāng)在一個站點退出的時候,其他兩個站點的cookie同樣也需要在瀏覽器中清除。這樣才可以實現(xiàn)單點退出。
這樣其實也很簡單,在理解了上述單點登錄的流程以后,單點退出只是按照上面的步驟將設(shè)置驗證cookie改成從響應(yīng)信息中移除cookie就可以實現(xiàn)了。
對于這種情況,不管是單點登錄也好,還是單點退出。都存在一個問題,在本例中我們只是有三個站點。如果說我們整個系統(tǒng)有10個20個或者更多站點,那像我們這樣來回的重定向會很影響效率。
方式二
接下來我們來介紹另一種方式。這種方式需要我們借助一個單獨的SSO服務(wù),專門做驗證用。而且我們還需要對于不同的站點的用戶要有一個統(tǒng)一的用戶數(shù)據(jù)。相對于前一種方式——瀏覽器需要存儲每個站點的cookie——來說,這種方式瀏覽器只需要存儲SSO服務(wù)站點的cookie信息。將這個cookie信息用于其他站點從而實現(xiàn)單點登錄。我們暫且將這個SSO服務(wù)站點成為www.SSOsite.com(以下簡稱SSOsite)。
在這種模型下,針對任何站點的請求都將會先重定向到SSOsite去驗證一個身份驗證cookie是否存在。如果存在,則驗證過的頁面將會發(fā)送給瀏覽器。否則用戶將會被重定向到登錄頁面。

為了理解此種方式,現(xiàn)在假設(shè)我們來運用這種模型實現(xiàn)以下兩個站點的單點登錄。
www.onmpw1.com(以下簡稱onmpw1)
www.onmpw2.com(以下簡稱onmpw2)
并且我們還有一個專門用來進行驗證的服務(wù)站點www.SSOsite.com(以下簡稱SSOsite) 。
第一部分

實現(xiàn)流程
·用戶請求onmpw1的一個需要驗證的頁面
·onmpw1向瀏覽器發(fā)送重定向到SSOsite的命令。并且在地址中添加一個返回地址(ReturnUrl)參數(shù)query string,該參數(shù)的值就是最初向onmpw1請求的地址。
·SSOsite會在請求中檢查是否有身份驗證cookie,或者任何用戶token。沒有這些信息,則會再次重定向到onmpw1,在重定向到onmpw1中的請求中會帶有參數(shù)讓用戶登錄的url參數(shù)和最初的瀏覽器請求onmpw1的地址——ReturnUrl。
·onmpw1會檢測從SSOsite重定向來的請求的參數(shù)。這時onmpw1了解到該用戶需要登錄,因此onmpw1會重定向到登錄界面,并且通知瀏覽器該請求不用再重定向到SSOsite。
第二部分

·用戶提供了身份驗證信息并且點擊了登錄按鈕?,F(xiàn)在不會再去重定向到SSOsite。這時,onmpw1調(diào)用SSOsite 中的web/WCF服務(wù)去檢查用戶提供的身份驗證信息。成功驗證,會將帶有token屬性的用戶對象返回給onmpw1。而這個token是每一次用戶登錄都會生成的。
·onmpw1標(biāo)記用戶已經(jīng)登錄成功,然后會生成一個URL地址,該地址會帶有用戶token,重定向到SSOsite。
·SSOsite檢查收到的URL地址,會在其中發(fā)現(xiàn)用戶token。通過該token可以知道用戶已經(jīng)成功登錄onmpw1了,所以SSOsite需要準(zhǔn)備驗證的cookie信息。因此,它會使用token在緩存中取出用戶信息來生成cookie信息,而且還會在cookie中設(shè)置一些其他的信息(例如過期時間等)。然后把cookie加入到響應(yīng)信息中。最后重定向到最初的ReturnUrl地址。同時token還是要被加在query string中帶過去的。
·瀏覽器得到重定向到onmpw1的命令,并且從SSOsite中得到cookie信息。因此瀏覽器將所屬域為SSOsite的cookie保存在本地。然后帶著token去請求onmpw1。
·現(xiàn)在onmpw1看到用戶token在query string 參數(shù)中,然后會再次通過web/WCF服務(wù)去在SSOsite上驗證token。驗證成功以后會將最初剛開始請求的頁面發(fā)送給瀏覽器用于向用戶輸出。
第三部分

·用戶現(xiàn)在去請求onmpw2。
·onmpw2重定向到SSOsite,同樣設(shè)置ReturnUrl為剛開始請求的onmpw2的頁面地址。
·瀏覽器接收到重定向的命令以后,因為本地存在SSOsite的cookie,所以會cookie加到請求中發(fā)送給SSOsite。
·SSOsite檢查接收到的請求中發(fā)現(xiàn)有cookie信息,首先會檢查該cookie信息是否過期,如果沒有過期,將會從cookie中提取出用戶token。然后帶著token重定向到最初的onmpw2中的地址。
·onmpw2發(fā)現(xiàn)請求中有用戶token,然后他會通過SSOsite的web/WCF服務(wù)驗證token的合法性。驗證成功以后,將最初瀏覽器請求onmpw2的頁面發(fā)送給瀏覽器用以向用戶輸出。
總結(jié)
哇哦,看起來有很多東西需要做。其實并沒有那么復(fù)雜。
起初,瀏覽器沒有所屬域為SSOsite的cookie信息。因此無論是點擊任何站點的需要驗證的界面都會跳轉(zhuǎn)到登錄頁(這個過程是由程序內(nèi)部重定向到SSOsite來檢查是否存在cookie的)。一旦用戶登錄成功,所屬域為SSOsite的,并且?guī)в械卿浻脩粜畔⒌腸ookie會被瀏覽器存儲在本地。
然后,當(dāng)用戶再次訪問需要驗證的頁面的時候,同樣請求會在被重定向到SSOsite,并且瀏覽器會帶上先前已經(jīng)保存的cookie信息。SSOsite檢索cookie,從中提取出用戶token,并帶著這個token重定向到最初請求的站點頁面。然后該站點會通過web/WCF服務(wù)去驗證token的合法性。然后將相應(yīng)的頁面發(fā)送給客戶端。
一旦用戶通過該單點登錄模型登錄到站點上,請求任何需要驗證的頁面都會內(nèi)部重定向到SSOsite驗證cookie和提取用戶token,然后將請求的頁面發(fā)送給瀏覽器輸出。
2:
上面的兩個方案,重點都是帶著參數(shù)(可能是URL,可能是token)重定向到另一個域名下,
去請求這個域名下的應(yīng)用程序,然后應(yīng)用程序在新域名下生成COOKIE或者token,
然后再帶著Token(方案一之生成COOKIE,不帶TOKEN)重定向回去。
下面我用PHP代碼模擬下
www.a.com????這個域名下有文件login.php 內(nèi)容如下
if(!array_key_exists('jump',$_GET)){setcookie("login",1);header('Location: http://www.b.com/login.php?jump');}
(圖1)
www.b.com????這個域名下也有個程序文件index.php(其實名字隨意)?內(nèi)容如下
if(array_key_exists('jump',$_GET)){setcookie("login",1);header('Location: http://www.a.com/login.php?jump');}
(圖2)
一開始,用戶在這兩個域名下,未登錄的話都是沒COOKIE的。
此時用戶先訪問 a域名的login.php,登錄a成功之后執(zhí)行上面圖1的代碼,
由于直接訪問的www.a.com/login.php,
并沒有jump這個參數(shù)(圖2說這個參數(shù)的作用),所以設(shè)置login成功,并用header重定向到了www.b.com/login且?guī)е鴍ump參數(shù)
當(dāng)b下的login.php收到j(luò)ump過來的參數(shù)時,說明是a登錄成功過來的,那么b下的程序就直接設(shè)置cookie為 login=1
(此時因為已經(jīng)到了b域名下執(zhí)行的應(yīng)用程序,所以COOKIE的有效域為www.b.com)
之后再由b再重定向到 a域名,帶著jump參數(shù),這樣a就不會再跳轉(zhuǎn)到b下了。
此時,www.a.com和www.b.com這兩個域名下,都有了登錄狀態(tài)的cookie。
用戶無論去那個站,都不用再登錄了。
方式一的原理即以上
方式二略
這兩個的重點,都是重定向到新域名之后生成新域名的cookie,然后再重定向回來