CAS (4) —— CAS瀏覽器SSO訪問順序圖詳解(CAS Web Flow Diagram by Example)
tomcat版本: tomcat-8.0.29
jdk版本: jdk1.8.0_65
nginx版本: nginx-1.9.8
cas版本: cas4.1.2
cas-client-3.4.1
參考來源:
CAS (1) —— Mac下配置CAS到Tomcat(服務端)
CAS (2) —— Mac下配置CAS到Tomcat(客戶端)
順序圖:(來源於http://jasig.github.io/cas/4.0.x/protocol/CAS-Protocol.html)
(1)用戶首次訪問(GET: https://app1.hoau.com:8413/cas1)
由於ssl是本地配置,瀏覽器不信任當前證書,所以會提示"NET::ERR_CERT_AUTHORITY_INVALID"
詳細信息如下:
點擊“高級”,選擇“繼續前往app1.hoau.com(不安全)”
(2)此時訪問未經身份驗證(unauthenticated)
所以服務器將請求轉到CAS,同時加上查詢參數“service”。
如何實現的呢?
我們可以看到http GET請求的Header中返回的狀態碼是“302 Found”
Request URL: https://app1.hoau.com:8413/cas1
Status Code: 302 Found
Response Header中,
Location:https://sso.hoau.com:8433/cas/login?service=https%3A%2F%2Fapp1.hoau.com%3A8413%2Fcas1
app1服務將請求重定向(redirect)到CAS服務。
(3)瀏覽器向CAS服務器發起帶參數的請求
Location:https://sso.hoau.com:8433/cas/login?service=https%3A%2F%2Fapp1.hoau.com%3A8413%2Fcas1
* 注意:此時客戶端瀏覽器中可能仍然帶有Cookie信息TGC與CASPRIVACY,但是在Response Header中發現,服務器會將這兩個Cookie置空,並且返回一個JSESSIONID
JSESSIONID=8534DCE475C44FF446D1DE2250426B1F
此時,CAS服務器發現用戶沒有SSO的Session。
(4)所以返回登錄頁面
(5)登陸SSO(用戶名/密碼:test01/psw01)
可以注意到此時是用POST方法將用戶名和密碼,包括登陸的Ticket一起發到CAS服務器
Form:
TGC:
然后CAS服務器會對提交的用戶名密碼進行驗證,如果驗證通過。
(6)CAS服務器會做幾件事情
- 創建SSO Session
- 創建CASTGC Cookie(這里圖中為TGC)
*注意:這個Session級別的Cookie 包含Ticket Granting Ticket(TGT)的信息。
Set-Cookie:TGC=eyJhbGciOiJIUzUxMiJ9.ZXlKaGJHY2lPaUprYVhJaUxDSmxibU1pT
2lKQk1USTRRMEpETFVoVE1qVTJJbjAuLmNFck5Eb2FkWGZkQndvMDBCN2gwNmcuU0
NlVjVaSllVTjJZbmNuRURmQjdUR2tPNGZ4Ny14RXAtZnctYWRhQlBUOU4wYS1ZU0d
PaE12MXNUUkxmRG1sYVV0U1NQM0prQzBrNERUOFZvd2dJU0VmYVBMdzFGdFNtdGhp
ZDN3cE1iVHZzbUlmOXFQYkZ3Q0F3eW9Pd3pjRmJHN1hzSHI2MHBhYjh5bFZzbHhPa
W12WlpRQnJveFpVR3hRQTJ1ZVZhbkNnQ09vYkxSY0RfQ0NOQnJ4Mm5aN19ocFJOYk
Z1LVZRdTV3c2FxUmxKTS05LWFGc1otQXBPWENXOEhjQlREUHBvOUVqWFhDZ204T00
xMXUtSldKdDBCRy1BVkl0ZUlKT0FGY3VoMXd4RWdYX0EuZUQzYjRGUkhKby1IamlC
bmNnMDlPZw.WwEL14ipWvub5c2PoE-Xq38I1ssN1glPclnXA7rKt7aV0boWAuR9WaUT8lPdMeL3ycjEv0whYAnaetv_hid0
8A; Path=/cas/; Secure; HttpOnly
最后這條請求的響應會同樣通過“302 Found”,將
(7)瀏覽器重定向到Protected App
Location:https://app1.hoau.com:8413/cas1?
ticket=ST-1-RNCht4LbpbALUYWPnR7K-cas01.sso.hoau.com
這時,瀏覽器會帶上獲得的ticket向App重新請求登陸,
(8)Protected App收到請求后
會向CAS服務器發送請求,驗證ticket的合法性
(9)然后CAS服務器會返回一個XML內容
(包括成功信息,認證對象和一些其他可選參數)
* 此處(8)、(9)兩步使用TCPMon接獲消息查看
(10)如果成功,Protected App會相應(7)的請求
通過“302 Found”將瀏覽器重定向到Protected App的目標頁面,同時設置Cookie的JSESSIONID
Content-Length:0
Date:Tue, 15 Dec 2015 01:56:41 GMT
Location:https://app1.hoau.com:8413/cas1;jsessionid=3D16483C31F8358A561E8EDCCC1C196D.tomcat1
Server:Apache-Coyote/1.1
Set-Cookie:JSESSIONID=3D16483C31F8358A561E8EDCCC1C196D.tomcat1; Path=/cas1/; Secure; HttpOnly
(11)瀏覽器帶Cookie:JSESSIONID訪問目標應用的頁面
(12)登陸成功,Protected App返回狀態碼200與頁面內容
再次訪問同一應用
順序圖:(來源於http://jasig.github.io/cas/4.0.x/protocol/CAS-Protocol.html)
(1)瀏覽器帶第一次認證后的Cookie:JSESSIONID訪問Protected App
(2)Protected App校驗Session Cookie
如果成功則返回首頁。
但是在測試時遇到了問題
發現再次訪問時,實際上有4段請求,與首次訪問唯一不同的是少掉了用戶名和密碼的輸入過程,但是Protected App上關於Session Cookie的校驗並沒有通過。
可以看到下圖中Protected App在(1)時又將瀏覽器重定向了CAS服務器,並且又為客戶端生成了新的Ticket
“ticket=ST-4-s2ffmz3oJZTax5XMV4x7-cas01.sso.hoau.com”
* 懷疑Protected App沒有維持Session的狀態
為了驗證這個想法,我們重新訪問
https://app1.hoau.com:8413/cas1
發現經過上面4段請求驗證后,瀏覽器url上會帶上jsessionid,如果將此請求參數刪除,那么會重新經過4段請求。
如果不刪除,而直接刷新頁面,系統交互的行為則如官網上順序圖描述的行為一致。
嘗試修改Protected App端的設置web.xml
增加SingleSignOutFilter
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
結
果仍然無效,還是4段請求。
嘗試更換瀏覽器進行測試
發現IE內核的瀏覽器行為,和我們之前測試用的Chrome一致,如果刪除url后的jsessionid,那么同樣會經過4段請求。
而Firefox瀏覽器會有些差異,在刪除url后的jsessionid后,Firefox的下次請求仍然帶有cookie
* 懷疑瀏覽器Cookie寫權限設置有問題
在Chrome瀏覽器中,“設置->高級->隱私設置->內容設置->Cookie”中管理例外情況,將app1.hoau.com和sso.hoau.com同時加入到例外設置中,
然后嘗試去掉url后的jsessionid參數,再次訪問
https://app1.hoau.com:8413/cas1
終於得到了我們想要的結果
訪問同域另一應用
順序圖:(來源於http://jasig.github.io/cas/4.0.x/protocol/CAS-Protocol.html)
(0)在訪問Protected App之后
https://app1.hoau.com:8413/cas1
如圖,我們可以發現CAS服務器已經生成了CASTGC,這個值會再訪問另一應用時使用到。
eyJhbGciOiJIUzUxMiJ9.ZXlKaGJHY2lPaUprYVhJaUxDSmxibU1pT2lKQk1USTRR
MEpETFVoVE1qVTJJbjAuLndBeWRVeGpIODE4Z0I4X29DSFBXYXcuVHVaOE5BN0tQZ
GJlSU5NSUZjNGZSQUVacDdUeGFFQkNJU2FONVFEYVRrVUpYR3VyUlpDeEloTktxTF
ljci1jNGJVdjdQLWc5MW9uaEUtU0VNSHV4RUU4dGpMeDRtMkg0RGNWbFJyTkJiR0N
EOUljSzNNZFZjV1BCRDduSFpwZ3E5VmI1emJMRV9GSmJjY1ZwZU5QdXRhOEp0M1g4
b0NLVjQzanozeHA1WlRfR0xkdjdmdjZlMmtEMnBTRXRIOG5UcS04NFpmNFlEcGZ4c
1Z2WDhlMVZLb0ZRcndyWUJpdGpnU0c4TkxPVHB5dy5TQURjZmN2cGhnbkJJT0NKNl
RLd1pB.hsIsZNJHWfrqQJ3kj4z18WctFpxeVPDQv9ONeK4yRVRSNBNprlfYJ_toa9
hbNozf_rGYOYySEdMJbSvR5IMa-A
(1)訪問另一應用
https://app2.hoau.com:8423/cas2
這時
(2)Protected App #2無法對用戶進行認證
服務器返回重定向狀態碼“302 Found”,將瀏覽器重定向到CAS服務器
Location:"https://sso.hoau.com:8433/cas/login?service=https%3A%2F%2Fapp2.hoau.com%3A8423%2Fcas2"
(3)瀏覽器嘗試訪問CAS服務器
並攜帶當前的Session和場景一中通過App #1認證時獲取的Cookie CASTGC
https://sso.hoau.com:8433/cas/login?service=https://app2.hoau.com:8423/cas2
(4)CAS服務器驗證Ticket並重定向
由於CAS服務器仍然存有之前CASTGC的狀態,因此將瀏覽器再次重定向到應用#2
Location:"https://app2.hoau.com:8423/cas2?
ticket=ST-58-TilmxEy20VOmDQuSdIx1-cas01.sso.hoau.com"
(5)瀏覽器通過重定向訪問應用#2的地址
https://app2.hoau.com:8423/cas2
然后
(6)Protected App #2會向CAS服務器再次發起請求
此時會攜帶Protected App #2生成的ticket
ticket=ST-58-TilmxEy20VOmDQuSdIx1-cas01.sso.hoau.com
(7)如果驗證成功,CAS服務器會返回包含成功信息的xml內容相應
並且將瀏覽器重定向到Protected App #2的登陸后頁面
* 此處(6)、(7)兩步使用TCPMon接獲消息查看,由於測試時忘記配TCPMon了,可能某些參數值對不上,在此致歉
(8)Protected App #2的驗證通過后,嘗試重定向到登陸成功的頁面
(9)瀏覽器攜帶CAS的Cookie請求App #2的登陸成功頁
Protected App #2再次校驗Session Cookie