國內私募機構九鼎控股打造APP,來就送 20元現金領取地址:http://jdb.jiudingcapital.com/phone.html
內部邀請碼:C8E245J (不寫邀請碼,沒有現金送)
國內私募機構九鼎控股打造,九鼎投資是在全國股份轉讓系統掛牌的公衆公司,股票代碼爲430719,爲「中國PE第一股」,市值超1000億元。 javascript
------------------------------------------------------------------------------------------------------------------------------------------------------------------php
原文地址: http://blog.sina.com.cn/s/blog_7a09f0920101agni.htmlhtml
最近在使用sina微博時,常常性交替使用 weibo.com 和 t.sina.cm.cn進入個人微博。發現當我在 t.sina.com.cn中登陸以後,直接切換至weibo.com,這時候在 weibo.com是已經登陸的,當我在 weibo.com進行註銷以後,再切換至 t.sina.com.cn,這時候在 t.sina.com.cn也已是註銷的狀態了。
對於SSO的實現方案及其機制,早已經不是什麼新鮮的技術了,從微軟爲.net提供的passport機制到java中開源的JBoss SSO、Oracle OpenSSO及經典的 Yale CAS等等之類的開源或一些商業SSO中間件都不失爲做爲單點登陸實現的選擇。固然一些企業也會選擇本身實現一套適合本身輕量級方案,如採用 SESSIONID轉遞或SESSION同步複製之類的。 能夠看得出SSO的價值也是具大的,就拿sina來講吧,增長 weibo.com域名以後,對於用戶來講來講沒有任何影響,即便你在 t.sina.com.cn中進行登陸,能夠無縫在兩域名之間隨意切換,對於它推廣weibo.com無非是大大的益處。
因爲近年來一直在使用 Yale的CAS做爲SSO的方案,以爲 SINA的SSO與Yale-CAS有不少殊途同歸之妙,因而便對SINA的SSO進行分析,其中的細節處理仍是很值的學習的。固然,因爲分析看到的 SINA SSO處理都只是一些表現或表面上的東西,再加上其大部分關鍵的sso js都已經被壓縮,及SERVER端的實現機制也只是靠本身的經驗及結合CAS的的一些原理進行猜想。其實本文應該叫 更比較貼切。
好吧,進入正題。
java
首先是進入 t.sina.com.cn,提交用戶名及密碼進行登陸,經過 Firebug能夠看到它經過相似Aajx POST到了 http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.3.12),以下圖所 示:
不難看出,其 http://login.sina.com.cn/sso/login.php 就是相似是 CAS 中的 Server,對sina的全部應用系統提供的統一登陸入口。上面的參數中有一個service參數,瞭解 CAS的GG應該知道 cas 在登陸的時候除了username 和 password一樣也有一個 service 參數,其CAS該參數含義是子應用系統的服務名標識及登陸成功以後所跳轉的地址。固然,sina這裏使用了 "miniblog"做爲微博的服務名,估計他在sso-server端對 miniblog 與登陸成功以後的地址進行映射,如 miniblog=http://t.sina.com.cn/,這樣就避免了CAS-client中轉入service= decodeURIComponent('http://t.sina.com.cn')之類的作法了。
這裏的登陸與CAS作法一致,將登陸驗證提交至統一的認證中心進行驗證處理,從而避免了跨子域和全域的問題。 驗證成功以後路轉的路徑就是service 所向的地址,驗證失敗以後則返回至當前登陸頁。下面就SSO中的一些登陸方面的核心問題作一些分析,看看SINA和CAS分別是如何處理的:
1.如何受權某個子系統容許其在sso-server進行登陸驗證呢,相似cas-server中的login-ticket;
對於cas來講,在首次進入 /cas/login頁時, 會產生一個一次性的login-ticket,也就是說在提交登陸驗證前必須向服務器請求一個login-ticket,在登陸提交時,須要將用戶名及密碼以及login-ticket進行提交至 cas-server端,cas-server端肯定login-ticket有效後纔會對用戶名及密碼進行認證。
看看sina如何處理的吧,繼續看firebug:
以上截圖是當我首次進行 t.sina.com.cn時,經過 ajax/jsonp的方式發起的一個請求,能夠看到返回的callback函數中的 json 串中包含了 nonce:"SXK19N"的屬性,參數名的漢譯是「一次」或「一次性」的意思,估計這裏的 nonce就是login-ticket,爲再一次確實,我再試着提交登陸看看,看它是否將該參數POST過去:
果真不出所料, nonce:"SXK19N"做爲參數提交過去了,證實所猜想的應該是正確的。
2.好比驗證碼跨域跨服務器致使從session沒法獲取的問題,咱們曾經遇到過;
貌似sina登陸沒有涉及到驗證碼之類的東西,當你屢次登陸失敗以後,它採用的是「您的登陸過於頻繁,請稍後再試吧」,這種方案確實比驗證碼要好的多,並且還避免了上面的說的問題。
3. 當我登陸失敗了,/sso/login.php 如何將登陸的錯誤信息返回給 t.sina.com.cn並讓它進行顯示呢,若是我登陸成功了/sso/login.php 經過什麼方式通知t.sina.com.cn呢,由於它這裏使用的是ajax方式登陸?
對於這方面,cas的處理是將錯誤信息以參數的方式返回給 client-login,如登陸失敗,重定向地址: http://cas-client.com?errocode=0,若是登陸成功,則直接 重定向至 service 中的url,並生成ST給客戶端,表示其已經在cas-server登陸成功了。
看看sina如何處理的吧,隨便輸入一個用戶名密碼,提交登陸,繼續經過firebug看看它的處理過程:
再看看t.sina.com.cn 中的html內容的變化:
以上圖1中發生了兩次請求,第一次登陸驗證是訪問 sso認證中心,它所返回response是一個html內容,第二次請求的地址: http://t.sina.com.cn /ajaxlogin.php framelogin=1& callback=parent.sinaSSOController.feedBackUrlCallBack&retcode=4038& amp;reason=���)
再結合以上圖2信息,看到 html 中發生了變化,建立了一個 id=ssoLoginFrame 的iframe,因而即可以得出,sina 的登陸並不是原生的ajax方式,而是經過建立iframe來模擬提交不刷新的登陸。也就是說,當用戶點擊登陸提交時,這時候它會經過js建立 iframe,將登陸提效至該iframe中。
既然已經知道它登陸是提交到iframe中,而非ajax方式,那麼對於以上截圖1中兩個請求爲何返回的都是HTML內容就很容易解釋了。再回到上面的 問題,/sso/login是如何通知t.sina.com.cn登陸失敗了呢? 首先在以上第一個截圖中返回的 HTML包含了一段 javascript:
jquery
location.replace的意思與location.href相似,一樣都是改變當前的URL地址,具體區別及作法能夠參考這裏及這裏。須要注意的這裏所說的經過location.replace改變當前的URL其它並不是改變t.sina.com.cn的地址,而是第二個截圖裏iframe中src的地址,由於這段HTML是在iframe中輸出的。
在 locaiton.replace 的地址中包含了一個 retcode 及 reason參數,估計這就是當前登陸的錯誤信息。在上面第一個截圖的第二個請求實際就是在iframe 中進行的 location.replace操做後的跳轉地址。關鍵看它輸出的html內容:
web
國內私募機構九鼎控股打造APP,來就送 20元現金領取地址:http://jdb.jiudingcapital.com/phone.html
內部邀請碼:C8E245J (不寫邀請碼,沒有現金送)
國內私募機構九鼎控股打造,九鼎投資是在全國股份轉讓系統掛牌的公衆公司,股票代碼爲430719,爲「中國PE第一股」,市值超1000億元。 ajax
------------------------------------------------------------------------------------------------------------------------------------------------------------------json
這段js是在 iframe中執行的,因此能夠經過 parent 進行訪問 t.sina.com.cn中的js,能夠確定 parent.sinaSSOController.feedBackUrlCallBack 就是告訴 t.sina.com.cn 當前已經登陸失敗了,而且將錯誤信息傳至該入該callback了。至此,已經完成了 /sso/login.php 對 t.sina.com.cn的信息傳送。 新浪果真是有一手呀,在CAS中AJAX登陸一直都是一個問題,而sina它巧妙的經過 iframe+callback 進行實現了。
接着,再看看它對於登陸成功以後如何通知 t.sina.com.cn的吧,先看看登陸成功以後 sina-sso-server 會作什麼,看firebug截圖:
重點在於 set-Cookie: tgc=TGT-MTc4NTc0NzM0Mw==-1305003116-ja- D51B2EB107B79FC50D8CA424BFE08907; 哈哈,熟悉CAS的應該會很熟悉這個,沒想到SINA的TGT與CAS的TGT不但參數命名,竟然連生成的規則也如出一轍,估計sina確定是參考了 cas 的實現機制。關於TGT是什麼或其做用能夠參考:CAS總結之Ticket篇。另外還有一個就是當登陸成功以後,sina-sso-server會將用戶登錄名等等放在sina.com.cn根域的cookie中。
而後再看看登陸成功以後 sina-sso-server所返回的response內容:
如下是從以上摘取JS部分:
api
首先再次聲明,以上firebug截圖中的請求處理,並不是 AJAX,而是在 t.sina.com.cn中放了一個iframe,輸出的 reponse都會至iframe當中.
以上的js主要重點在於:
跨域
仍是經過設置當前iframe中src地址,再看看跳轉至http://t.sina.com.cn/ajaxlogin.php後的response內容吧:
返回用戶信息(從cookie中獲取的),而且仍是相似上面的作法,經過 parent.sinaSSOController.feedBackUrlCallBack回調t.sina.com.cn中的js,告訴它這個用戶已經登陸成功了。
因而t.sina.com.cn便進行跳轉至 t.sina.com.cn/dengers 中,從而實現登陸。
總體的處理流程以下:
4. 當我在t.sina.com.cn中登陸後,切換至weibo.com,weibo.com我應該也是已經登陸的,如何作到呢?
對於這個問題,CAS中的處理就是,當我進入 weibo.com的時候,立刻跳轉至 /cas/login,而後在login中判斷cookie是否存在TGT,若是存在,並肯定其有效性後,則認爲你已經登陸,併爲你生成一個ST,將ST 做爲ticket參數使其重定向至 weibo.com?ticket=TG-xxxx 並登陸。
看看sina怎麼處理的吧,首先我直接在t.sina.com.cn登陸成功。而後再新建一個選項卡,輸入 weibo.com:
能夠看得出,當我進入 weibo.com以後,sina並無直接進入 weibo.com的主頁,而是立刻重定向至: http://login.sina.com.cn/sso/login.php?url=http://weibo.com/&_rand=1305008634.5127&gateway=1&service=miniblog&useticket=1&returntype=META 與cas的作法確實一致。 再看看該 login.php的Response 信息,主要是JS:
看到這裏以後,不得不懷疑 SINA 的 SSO 是否是用的就是 CAS 啊!!不但連 TGT 參數名同樣,連ST規則及參數名也如出一轍,其處理機制也十分類似。
到這裏以後就與 CAS 的處理同樣了,就不詳細寫了,能夠參考 CAS相關文章。
──────────
PS:因爲在分析過程當中裏面的不少SSO關鍵JS都壓縮了,因此不免會存在偏差。 不過SINA的SSO不少細節方面確實處理的很好,做爲互聯網 應用的話,若是單純的只是把 CAS DOWNLOAD 下來,而後直接配配就用的話不少方面的處理仍是很不到位的。 有時間我把咱們CAS參考 SINA 調整一下。
到這裏,不得不說的一個事情就是,以前在分析淘寶cookie如何跨域獲取時, 你們都說出了一個taobao的jsonp實際存在必定的安全隱患。後面那個淘寶的GG看到以後加入Refer的判斷。而如今,在分析的過程當中發現新浪也 有這樣的問題,能夠嘗試一下,隨便在本地創建一個html,引入jquery,而後使用下面的JS,就能夠獲取到sina中的登陸郵箱名等信息,前提是你 須要先在sina中登陸:
國內私募機構九鼎控股打造APP,來就送 20元現金領取地址:http://jdb.jiudingcapital.com/phone.html
內部邀請碼:C8E245J (不寫邀請碼,沒有現金送)
國內私募機構九鼎控股打造,九鼎投資是在全國股份轉讓系統掛牌的公衆公司,股票代碼爲430719,爲「中國PE第一股」,市值超1000億元。
------------------------------------------------------------------------------------------------------------------------------------------------------------------