1. 程式人生 > >CAS單點登出問題

CAS單點登出問題

文章來源:http://blog.csdn.net/tch918/article/details/22276627

自從CAS 3.4很好的支援了單點登出功能,配置也很簡單。

之前版本因為在CAS伺服器通過HttpClient傳送訊息時並未指定為POST方式,所以在CAS客戶端的登出Filter中沒有收到POST請求(要知道Filter只對Post請求起作用),也就沒有做session銷燬處理。

兩個業務系統APP1和APP2

在沒有配置單點退出時,效果是這樣子的

1:登入APP1,然後經過CAS認證後進入APP1再訪問APP2無需要認證

2:在APP1中連線到cas的logout地址,現象登出成功介面,然後再訪問APP1,還是可以進去的,因為APP1將使用者的登入票據存入了session。

那麼實現了單點退出後的效果應該是這樣子的:

1:登入APP1,然後經過CAS認證後進入APP1再訪問APP2無需要認證

2:使用者在APP1或者APP2點選登出,顯示CAS的登出成功頁面,然後再訪問APP1或者APP2都需要再次認證。

具體配置為在APP1和APP2的web.xml檔案中增加:

  1. <listener>
  2.         <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
  3. </listener
    >
  4.  <filter>
  5.        <filter-name>CAS Single Sign Out Filter</filter-name>
  6.        <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
  7.   </filter>
  8. <filter-mapping>
  9.     <filter-name>CAS Single Sign Out Filter</filter-name>
  10.     <
    url-pattern>/*</url-pattern>
  11.  </filter-mapping>


SingleSignOutFilter,主要是在有ticket引數的時候,將session放到sessionMappingStorage,如果引數中存在logoutRequest,則登出session,那什麼時候去登出sessionMappingStorage的東西呢?這是靠SingleSignOutHttpSessionListener來實現的,當有session被銷燬的時候,觸發將sessionMappingStorage中對應sessionid中的資料刪除。

所以在配置單點登出的時候,一定要配置這個監聽器,否則客戶端很容易導致記憶體溢位的。讓我們先來看看SingleSignOutFilter的整體邏輯。


那麼這個是在什麼時候會觸發呢,這個是在你登陸的任意客戶端,呼叫https://localhost:8080/logout這個取得cookie裡面的TGT資料,找到TGT中關聯的所有ST對應的地址(即多個cas client,向每個地址方式一個http請求,並傳遞logoutRequest引數。

來看看原始碼是怎麼實現

  1. publicvoid doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {    
  2.       // 轉換引數  
  3.     final HttpServletRequest request = (HttpServletRequest) servletRequest;    
  4.     //判斷引數中是否具有artifactParameterName屬性指定的引數名稱,預設是ticket  
  5.       if (handler.isTokenRequest(request)) {    
  6.         // 如果存在,在本地sessionMappingStorage中記錄session。  
  7.           handler.recordSession(request);     
  8.       } elseif (handler.isLogoutRequest(request)) {//判斷是否具有logoutParameterName引數指定的引數,預設引數名稱為logoutRequest  
  9.         // 如果存在,則在sessionMappingStorage中刪除記錄,並登出session。  
  10.         handler.destroySession(request);    
  11.           // 登出session後,立刻停止執行後面的過濾器  
  12.           return;    
  13.       } else {    
  14.           log.trace("Ignoring URI " + request.getRequestURI());    
  15.       }    
  16.       //條件都不滿足,繼續執行下面的過濾器  
  17.       filterChain.doFilter(servletRequest, servletResponse);    
  18.   }    

如果直接訪問CAS的logout話,會出現登出成功頁面,其實大部分情況下這個頁面是沒有必要的,更多的需求可能是退出後顯示登入頁面,並且登入成功後還是會進入到之前的業務系統,那麼可以修改cas-servlet.xml檔案,在"logoutController"的bean配置中增加屬性“followServiceRedirects”,設定為“true”,然後在業務系統的登出連線中加入"service引數",值為業務系統的絕對URL,這樣就OK了,如你的業務系統URL為:http://localhost:8080/casClient,那麼登出URL就為:http://localhost:8080/cas/logout?service=http://localhost:8080/casClient

可能因為:

1:你的CAS伺服器將cookie設定成了瀏覽器有效,那麼表示如果瀏覽器不關閉,則一直有效。

在WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml中設定cookie有效期,預設配置cookie有效期為-1

2:你的應用中登出的filter-mapping沒有放在所有mapping之前