最近忙死了,很久都沒寫部落格了。公司要做sso應用,有部門有需求希望能夠在自己的應用端定義登陸頁面,而不是登陸全跳轉到cas統一登陸界面。看了下cas伺服器端源碼,還算好懂,于是脫了衣服開始搞。。。。。
這篇主要是介紹修改原理等,如果嫌麻煩,可以跳過這篇直接看實作篇
兩個方案,分别支援用戶端使用iframe+js和重定向技術進行遠端登入,在此先給出重定向技術的方案。
此方案主要是通過頁面重定向來實作用戶端獨立登陸頁面
基本原理
首先,在我們修改之間,先了解以下cas運作基本原理。cas伺服器,用戶端(應用),浏覽器的序列圖如下:
其中:
st:service ticket,用于用戶端應用持有,每個st對應一個使用者在一個用戶端上
tgt:ticket granting ticket,存儲在cas伺服器端和使用者cookie兩個地方
cas伺服器持有st與tgt+用戶端的映射關系,用戶端持有st與使用者session的映射關系,在renew的情況下,每次用戶端根據使用者session将st發送給cas伺服器端,伺服器端檢驗st是否存在即可知道此使用者是否已登陸。在普通情況下,使用者第一次登陸應用時,用戶端将使用者頁面重定向到cas伺服器,伺服器取出使用者cookie中的tgt,檢驗是否在伺服器中存在,若存在則生成st傳回給用戶端 (若不存在則要求登陸,登陸成功後同樣傳回st給用戶端),用戶端拿到st後再發送給cas伺服器認證是否為真實st,認證成功即表示登陸成功
我們可以看到,其實我們需要做的就是第2步中傳回的登陸頁面由伺服器改放到用戶端,然後讓第3步中由使用者在用戶端上輸入使用者名密碼但送出到cas伺服器端,登陸成功與失敗都将轉向用戶端。
伺服器詳細登陸流程
對于上一節講述的整體登陸流程,cas 3.3.1伺服器端上是依賴于spring webflow 1.0.3實作的,其主要流程在/web-inf/login-webflow.xml中配置,配置的頁面流活動圖如下(有删節):
圖中命名均按照webflow配置檔案中的命名,圖解如下:
action state圖示表示webflow配置檔案中的action-state或view-state節點
decision圖示表示webflow配置檔案中的decision-state節點
initial state圖示表示webflow配置檔案中的start-state節點
final state圖示表示webflow配置檔案中的end-state節點
登陸的流程依照圖上說明,在此不再累述,下面簡單說明下cas伺服器端spring webflow的運作
首先cas在/web-inf/web.xml中配置命名為cas的servlet以攔截輸入請求,若不在cas servlet mapping範圍内的資源路徑請求均轉向到/login上:
<servlet>
<servlet-name>cas</servlet-name>
<servlet-class>org.jasig.cas.web.init.safedispatcherservlet</servlet-class>
<init-param>
<param-name>publishcontext</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<url-pattern>/login</url-pattern>
</servlet-mapping>
...
<!-- 其他cas servlet mapping -->
所有映射到cas servlet上的請求都将經過/web-inf/cas-servlet.xml檢查确定進入哪個action,cas-servlet.xml中最重要的兩個bean就是handlermappingb和handlermappingc
handlermappingb配置了登陸流程進入的路徑映射,而handlermappingc則配置了其他的流程的路徑映射。/web-inf/login-webflow.xml流程配置檔案即是在handlermappingb中通過/login映射進入的。
webflow依據一個生成的flowexecutionkey來确定一個流程執行個體走到了哪一步,每次頁面流程運轉總是需要送出這個flowexecutionkey來告訴webflow它是從流程的哪個位置出發的有了以上理論作為依據,我們在下一節就可以根據自己的需要修改流程,使之支援遠端登入了
伺服器登陸流程修改目标
修改後的登陸流程活動圖如下:
圖中橙色為我們修改的流程節點,這裡我們增加了一個開始節點remotelogin和一個結束節點
remotecallbackview,删除了原有的loginformview節點、 viewgenericloginsuccess以及
renew節點(renew節點由于系統無此需求而删除),然後将所有這些節點的轉向全部都轉向
到remotecallbackview節點,因為登陸和顯示登陸成功資訊都應該是用戶端完成的