博主最近使用CAS做單點登錄 , 測試demo中, 碰到如下問題, 解決過程曲折, 現分享如下:
問題一: CAS單點登出功能 bug 描述:
問題描述:
開發環境下, idea中tomcat插件運行CAS Client_1和Client_2兩個項目, 將CAS Server部署在Linux系統上的tomcat中:
1. 當訪問Client_1時, 進行登錄, 此時可直接訪問Client_2, 無需登錄,即單點登錄功能正常;
2. 當訪問單點登出地址後, 頁面顯示登出成功, 此時再次訪問Client_1, 被要求再次登錄, 但是訪問Client_2卻無需登錄, 可以直接訪問;
Client_1關鍵配置信息(web.xml中) (Client_1除端口號外 相同):
<!-- ======================== 單點登錄開始 ======================== -->
<!--TODO 單點登出-->
<!-- 單點登出過濾器 用於單點退出,該過濾器用於實現單點登出功能,可選配置 -->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!-- 該過濾器用於實現單點登出功能,可選配置。 -->
<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>
<!--TODO 單點登錄-->
<!-- 該過濾器負責用戶的認證工作,必須啓用它 -->
<filter>
<filter-name>CASFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>http://192.168.25.129:8082/cas/login</param-value>
<!--這裏的server是服務端的IP -->
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:9018</param-value>
<!--當前系統的客戶端的端口號-->
</init-param>
</filter>
<filter-mapping>
<filter-name>CASFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 該過濾器負責對Ticket的校驗工作,必須啓用它 -->
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>http://192.168.25.129:8082/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:9018</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
此時考慮: 理想情況下整個登陸登出過程:
1. 訪問Client_1, 要求進行登錄, 於是基於Client_1跳轉到登錄頁面, 並向 casServer發出認證請求, 此時爲認證操作, 服務器判斷賬號密碼後返回ticket;
2. 此時訪問Client_2, 因爲持有ticket, 所以casServer直接驗證ticket有效, 允許訪問, 且再次訪問時, 只要ticket不變, 是不需要經過casServer的;
3. 登出: 訪問casServer的登出鏈接 /cas/logout, 要求登出, casServer銷燬認證信息, 並通知認證過的系統, 要求銷燬該瀏覽器客戶端的ticket許可,;
4. 登出後, Client_1 或 Client_2 再次登錄時, 因爲ticket失效, 則被要求再次登錄, 因爲回到步驟1 階段;
問題分析:
1. 目前的問題是, 第一次認證的系統 Client_1 可以被有效登出, 其餘持ticket去驗證的系統 Client_2 , 未被有效登出;
2. 故問題出在: casServer未能通知後續持ticket進行驗證登錄的系統 Client_2 去銷燬該瀏覽器的認證信息, 導致Client_2可以繼續被該瀏覽器持過期ticket訪問 ;
問題原因:
casServer登出時, 無法通知ip設置爲: localhost 的驗證客戶端 (認證客戶端(即跳轉登陸的客戶端)可以識別)
問題解決:
將客戶端ip設置爲本機IPV4地址, 即windows系統中輸入ipconfig 或linux系統中輸入 ifconfig, 獲取ipv4地址, 且保證改地址能被casServer所在linux系統ping通;
關鍵配置如下:
錯誤:
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:9018</param-value>
<!--當前系統的客戶端的端口號-->
</init-param>
正確如下(共兩處, 認證和驗證過濾器均需要):
<init-param>
<param-name>serverName</param-name>
<param-value>http://192.168.25.1:9018</param-value>
<!--當前系統的客戶端的端口號-->
</init-param>
後續:其實可以只修改驗證過濾器的配置, 因爲認證過濾器配置爲localhost是可以正確識別的;
正確的完整配置 (web.xml中) 供參考: (和spring整合時, 配置bean的屬性即可, 原理相同)
<!-- ======================== 單點登錄開始 ======================== -->
<!--TODO 單點登出-->
<!-- 單點登出過濾器 用於單點退出,該過濾器用於實現單點登出功能,可選配置 -->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!-- 該過濾器用於實現單點登出功能,可選配置。 -->
<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>
<!--TODO 單點登錄-->
<!-- 該過濾器負責用戶的認證工作,必須啓用它 -->
<filter>
<filter-name>CASFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>http://192.168.25.129:8082/cas/login</param-value>
<!--這裏的server是服務端的IP -->
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://192.168.25.1:9019</param-value>
<!--當前系統的客戶端的端口號-->
</init-param>
</filter>
<filter-mapping>
<filter-name>CASFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 該過濾器負責對Ticket的校驗工作,必須啓用它 -->
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>http://192.168.25.129:8082/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://192.168.25.1:9019</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
問題二:cas jar包cas-client-core由3.3.3切換到3.4.1時, 報錯:
嚴重: Exception starting filter CAS Single Sign Out Filter
java.lang.IllegalArgumentException: casServerUrlPrefix cannot be null.
原因:
3.4.1版本(其它版本未實測, 可參考)需要手動配置登出鏈接的前綴, 故單點登出過濾器的配置中增加相關屬性即可:
解決辦法:
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>https://cas服務器的ip加端口號/cas</param-value>
</init-param>
</filter>
----------------------------------------------------------------------------------------結束---------------------------------------------------------------------------------------
轉載請標明出處: 划船一哥