一、單點登錄系統開發需要注意的問題
1.單點登錄系統需要支持jsonp請求?
單點登錄系統主要是向其他系統提供用戶身份驗證服務,因此需要提供對外接口,而外部系統通過接口訪問時,必然涉及跨域問題,因此需要單點登錄系統支持jsonp消息轉換,即能正確處理跨域請求。否則,請求接收到的數據解析失敗,chrome debug中提示“Uncaught SyntaxError: Unexpected token <”。
單點登錄系統主要是向其他系統提供用戶身份驗證服務,因此需要提供對外接口,而外部系統通過接口訪問時,必然涉及跨域問題,因此需要單點登錄系統支持jsonp消息轉換,即能正確處理跨域請求。否則,請求接收到的數據解析失敗,chrome debug中提示“Uncaught SyntaxError: Unexpected token <”。
2.超時問題
我們提供的CAS開源單點登錄SSO組件,它部署節點主要有2個:SSO服務器(部署內容為一個web應用)、應用系統客戶端(部署內容為cas客戶端casclient.jar包和相關配置文件)。因此我們根據SSO機制分析一下什么情況下會出現超時。多個應用系統進行SSO集成后,SSO單點登錄過程中,登錄成功后,應用系統客戶端(以下用瀏覽器客戶端為例)的session會保存認證后的用戶上下文,SSO服務器會生成一個用戶憑證票據(TGT)並緩存起來,瀏覽器客戶端會保存TGC(瀏覽器cookie中存儲的TGT),TGT是作為發放SSO訪問服務的票據(ST)的一個憑證票據,發放ST票據后才能正常訪問。而瀏覽器客戶端的session會超時(如一般web應用客戶端可以設置session的timeout值為30分鍾或更長),超時后會讓session失效,清空用戶上下文,TGC因為仍然是保存在瀏覽器cookie中,只有關閉瀏覽器才會清除。SSO服務器端的超時主要是TGT、ST超時,我們一般會設置超時值TGT為2小時,ST為5分鍾。關於ST票據使用,一般在首次SSO訪問服務時攜帶着該票據參數,驗證票據后能正常訪問后,SSO服務器就將此ST銷毀失效了;關於TGT票據的使用,一般是正常訪問時一直保持為超時時間(2小時),除非做單點退出會銷毀TGT。
基於以上分析,我們可以得出結論,SSO的超時主要涉及2個要素:瀏覽器的session超時值、TGT的超時值。一般系統設置TGT的超時值>瀏覽器的session超時值,那么可能有2種超時情況:1.TGT超時(瀏覽器session超時值小,自然也超時);2.瀏覽器session超時,TGT不超時。
基於以上分析,我們可以得出結論,SSO的超時主要涉及2個要素:瀏覽器的session超時值、TGT的超時值。一般系統設置TGT的超時值>瀏覽器的session超時值,那么可能有2種超時情況:1.TGT超時(瀏覽器session超時值小,自然也超時);2.瀏覽器session超時,TGT不超時。
第一種“1.TGT超時”,這個處理很簡單,用戶的有效憑證票據都失效了,自然要重新取得有效憑證票據TGT,需要做的就是重新跳轉到登錄頁面重新登錄。
第二種”2.瀏覽器session超時,TGT不超時“,這時SSO服務器的TGT票據,以及瀏覽器客戶端的TGC(cookie中的TGT)仍然有效。瀏覽器客戶端再次SSO訪問時就可以攜帶TGC(與服務器的TGT對應),向SSO服務器重新發送取得票據ST請求,取得票據ST后,攜帶着有效ST票據可以正常訪問應用系統了。這個過程是瀏覽器客戶端與SSO服務器的一個通訊交互,用戶可能感覺不到,不會出現中斷,好像能連續訪問,這是為了給用戶一個友好的訪問體驗。明白這個機制,就知道實際上是SSO機制在后台起作用了。
3.jsessionid問題
jsessionid是Java客戶端與應用服務器維持session的一個標識,其他語言客戶端(如PHP)有其他標識關鍵字,具體是什么還不太了解。jsessionid一般存在於瀏覽器cookie中的(這個一般java客戶端連接到應用服務器會自動執行的),一般情況下不會出現在url中,服務器會從客戶端的cookie中取出來,但是如果瀏覽器禁用了cookie的話,就要重寫url了,顯式的將jsessionid重寫到Url中,方便服務器來通過這個找到session的id。CAS開源單點登錄SSO組件就提供了這個機制。我研究了CAS源碼,基本明白了jsessionid的處理機制。大致原理如下:用戶訪問業務系統,SSO客戶端攔截,重定向到SSO服務器認證時,就將請求路徑uri中寫入";jsessionid=具體的session值",SSO服務器可以分辨出這個標識值與其他客戶端請求不同,進行認證處理,返回的響應給客戶端cookie同時也設置了jsessionid的值,之所以在uri和cookie中都設置了jsessionid,是為了雙重保障能設置jsessionid值。最后單點登錄成功后,返回業務系統訪問地址也帶有jsessionid參數,這個在uri地址中看起來很別扭。
jsessionid是Java客戶端與應用服務器維持session的一個標識,其他語言客戶端(如PHP)有其他標識關鍵字,具體是什么還不太了解。jsessionid一般存在於瀏覽器cookie中的(這個一般java客戶端連接到應用服務器會自動執行的),一般情況下不會出現在url中,服務器會從客戶端的cookie中取出來,但是如果瀏覽器禁用了cookie的話,就要重寫url了,顯式的將jsessionid重寫到Url中,方便服務器來通過這個找到session的id。CAS開源單點登錄SSO組件就提供了這個機制。我研究了CAS源碼,基本明白了jsessionid的處理機制。大致原理如下:用戶訪問業務系統,SSO客戶端攔截,重定向到SSO服務器認證時,就將請求路徑uri中寫入";jsessionid=具體的session值",SSO服務器可以分辨出這個標識值與其他客戶端請求不同,進行認證處理,返回的響應給客戶端cookie同時也設置了jsessionid的值,之所以在uri和cookie中都設置了jsessionid,是為了雙重保障能設置jsessionid值。最后單點登錄成功后,返回業務系統訪問地址也帶有jsessionid參數,這個在uri地址中看起來很別扭。
解決方法,如下:
(1) 可以在登錄頁面地址的請求地址參數中加入參數”&method=POST“(記住這里要求POST大寫),這樣就可以在最后返回的訪問uri中不顯示jsessionid。
(1) 可以在登錄頁面地址的請求地址參數中加入參數”&method=POST“(記住這里要求POST大寫),這樣就可以在最后返回的訪問uri中不顯示jsessionid。
4.單點退出時有時子系統未能正常退出
我們知道正常情況下,以用戶A單點登錄系統,正常訪問各子系統,然后執行單點退出時,退出成功后一般跳轉回到登錄頁面要求重新登錄,這時各已登錄的子系統session被銷毀,再次以另一個用戶B登錄進入后,各子系統顯示的應當是用戶B的數據信息。可是有時卻發現有些子系統仍然顯示的是用戶A的數據信息,這屬於偶發現象。現在分析一下產生這種情況可能的原因,找出解決辦法。
5.有些請求路徑不需要單點登錄過濾器攔截
業務系統web應用在使用單點登錄組件時,有些請求路徑不需要單點登錄過濾器攔截,比如公共開放的路徑,不需要認證都可以自由訪問的路徑,單點登錄過濾器配置的映射路徑一般以通配符匹配路徑,但要把這些路徑單獨提取出來,讓過濾器不攔截做單點登錄處理,就需要對原有過濾器進行擴展改造,才能實現這個功能。
業務系統web應用在使用單點登錄組件時,有些請求路徑不需要單點登錄過濾器攔截,比如公共開放的路徑,不需要認證都可以自由訪問的路徑,單點登錄過濾器配置的映射路徑一般以通配符匹配路徑,但要把這些路徑單獨提取出來,讓過濾器不攔截做單點登錄處理,就需要對原有過濾器進行擴展改造,才能實現這個功能。
6.不同應用服務實現要求SSO客戶端做適應性改造
不同應用服務,對請求的處理方式不同,SSO客戶端常規方法不能處理的需要進行適應性改造。我們先看一下SSO客戶端常規方法處理請求,web應用中定義一個過濾器casfilter,並配置對安全資源攔截,首次登錄系統、或者訪問超時時,安全資源的請求被過濾器casfilter攔截,將安全資源路徑包裝為service參數,並重定向(http狀態為302)到SSO服務器地址進行認證,輸入憑證信息(用戶名、密碼等),SSO服務器經過認證、驗證票據機制處理,認證成功后,登錄通過后繼續訪問安全資源,再次訪問安全資源時,過濾器casfilter攔截,根據用戶上下文判斷用戶已經登錄,就不再攔截安全資源,直接正常訪問安全資源。而有些應用中使用其他方式處理請求,按上述常規方法不好處理,下面舉實例來看看解決方案。
不同應用服務,對請求的處理方式不同,SSO客戶端常規方法不能處理的需要進行適應性改造。我們先看一下SSO客戶端常規方法處理請求,web應用中定義一個過濾器casfilter,並配置對安全資源攔截,首次登錄系統、或者訪問超時時,安全資源的請求被過濾器casfilter攔截,將安全資源路徑包裝為service參數,並重定向(http狀態為302)到SSO服務器地址進行認證,輸入憑證信息(用戶名、密碼等),SSO服務器經過認證、驗證票據機制處理,認證成功后,登錄通過后繼續訪問安全資源,再次訪問安全資源時,過濾器casfilter攔截,根據用戶上下文判斷用戶已經登錄,就不再攔截安全資源,直接正常訪問安全資源。而有些應用中使用其他方式處理請求,按上述常規方法不好處理,下面舉實例來看看解決方案。
6.1.Ajax客戶端
公司有一個應用系統使用Ajax客戶端來處理請求並取得響應,在訪問超時時,Ajax客戶端請求由於使用異步處理技術(只局部刷新頁面),不能將請求繼續302重定向到SSO服務器重新認證處理,不能繼續訪問安全資源,界面響應處於一直延遲狀態,很不友好。我們針對此應用進行適應性改造。改造要點如下:
公司有一個應用系統使用Ajax客戶端來處理請求並取得響應,在訪問超時時,Ajax客戶端請求由於使用異步處理技術(只局部刷新頁面),不能將請求繼續302重定向到SSO服務器重新認證處理,不能繼續訪問安全資源,界面響應處於一直延遲狀態,很不友好。我們針對此應用進行適應性改造。改造要點如下:
我們約定應用系統的一個Ajax請求的標記(如ajaxRequestFlag=ajaxRequest),在安全資源ajax調用請求時攜帶此請求參數,還約定一個超時請求的響應狀態值(如555),SSO客戶端的過濾器casfilter的相應類程序對此約定進行了相應的改造。
應用系統的安全資源頁面中引入文件(HttpStatusSSO.js)SSO對Axax請求的http狀態的處理,其中有超時時的狀態處理、判斷是否登錄、驗證票據等的處理,都是通過ajax請求方式來處理的,其中依賴一個驗證票據的資源ticketValidate.jsp。
經過上述改造后,應用系統的安全資源發送攜帶ajax請求標記的請求,在超時請求時,SSO客戶端返回約定響應碼(555),HttpStatusSSO.js文件判斷處理后轉發給相應的登錄頁面重新認證。單點登錄的訪問也能夠正常的實現功能。這樣只擴展了SSO客戶端組件的實現,向下版本兼容,保證了SSO組件的統一完整性。
6.2.多域認證
有時我們遇到,不同子系統的認證實現的數據源可能來自一個用戶數據庫。我公司就是這種情況,采用Saas模式運營的軟件,認證的用戶來源於不同的租戶或者域,基於這樣的情況,我們對SSO進行了擴展,主要提供了認證接口,認證實現上,可以在認證時動態取得租戶對應的數據源,對用戶進行認證處理。
有時我們遇到,不同子系統的認證實現的數據源可能來自一個用戶數據庫。我公司就是這種情況,采用Saas模式運營的軟件,認證的用戶來源於不同的租戶或者域,基於這樣的情況,我們對SSO進行了擴展,主要提供了認證接口,認證實現上,可以在認證時動態取得租戶對應的數據源,對用戶進行認證處理。
6.3.SSO集中認證登錄頁面需要在業務子系統中定制
SSO集中認證的登錄頁面默認是放在SSO服務器端的,樣式也很不好看,用戶需要把登錄頁面放在業務子系統中自行定制,我們對SSO進行了擴展,思路也很簡單,主要是將顯示默認登錄頁面的調用,變成了遠程調用業務子系統的頁面地址,這個地址可以作為配置參數來配置。
SSO集中認證的登錄頁面默認是放在SSO服務器端的,樣式也很不好看,用戶需要把登錄頁面放在業務子系統中自行定制,我們對SSO進行了擴展,思路也很簡單,主要是將顯示默認登錄頁面的調用,變成了遠程調用業務子系統的頁面地址,這個地址可以作為配置參數來配置。
二、關於用戶注冊,需要注意的幾個問題
1.避免用戶密碼泄露
(1) 在前端對密碼MD5加密后再傳給后台。
(2)后端:登錄時用戶信息存入redis緩存時,密碼禁止存儲,更要禁止傳到前端頁面。
2.用戶注冊信息的校驗
(1)前端校驗
(2)后端校驗;
三、上線后可能遇到的問題
1.可能遇到Cookie無法寫入的問題
原因:Nginx向Tomcat轉發請求時,丟失了域名。
通過request對象獲取請求的域名時,沒有獲取到真實的請求域名,導致cookie寫入失敗。 解決:
分析:用戶--->Nginx-->Tomcat
在nginx做請求轉發時將請求的域名丟失了,導致在tomcat中無法獲取真實的請求域名。