出處:http://blog.csdn.net/tch918/article/details/22276627java
自從CAS 3.4就很好的支持了單點註銷功能,配置也很簡單。web
以前版本由於在CAS服務器經過HttpClient發送消息時並未指定爲POST方式,因此在CAS客戶端的註銷Filter中沒有收到POST請求(要知道Filter只對Post請求起做用),也就沒有作session銷燬處理。spring
兩個業務系統APP1和APP2瀏覽器
在沒有配置單點退出時,效果是這樣子的服務器
1:登陸APP1,而後通過CAS認證後進入APP1,再訪問APP2無須要認證cookie
2:在APP1中鏈接到cas的logout地址,現象註銷成功界面,而後再訪問APP1,仍是能夠進去的,由於APP1將用戶的登陸票據存入了session。session
那麼實現了單點退出後的效果應該是這樣子的:app
1:登陸APP1,而後通過CAS認證後進入APP1,再訪問APP2無須要認證this
2:用戶在APP1或者APP2點擊註銷,顯示CAS的註銷成功頁面,而後再訪問APP1或者APP2都須要再次認證。url
具體配置爲,在APP1和APP2的web.xml文件中增長:
<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>
註銷的Filter要在其它Filter以前,界面的註銷鏈接到CAS的logout地址,如http://localhost:8080/cas/logout
SingleSignOutFilter,主要是在有ticket參數的時候,將session放到sessionMappingStorage,若是參數中存在logoutRequest,則註銷session,那何時去註銷sessionMappingStorage的東西呢?這是靠SingleSignOutHttpSessionListener來實現的,當有session被銷燬的時候,觸發將sessionMappingStorage中對應sessionid中的數據刪除。
因此在配置單點登出的時候,必定要配置這個監聽器,不然客戶端很容易致使內存溢出的。讓咱們先來看看SingleSignOutFilter的總體邏輯。
那麼這個是在何時會觸發呢,這個是在你登錄的任意客戶端,調用https://localhost:8080/logout,這個取得cookie裏面的TGT數據,找到TGT中關聯的全部ST對應的地址(即多個cas client),向每一個地址方式一個http請求,並傳遞logoutRequest參數。
來看看源代碼是怎麼實現的:
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException { // 轉換參數 final HttpServletRequest request = (HttpServletRequest) servletRequest; //判斷參數中是否具備artifactParameterName屬性指定的參數名稱,默認是ticket if (handler.isTokenRequest(request)) { // 若是存在,在本地sessionMappingStorage中記錄session。 handler.recordSession(request); } else if (handler.isLogoutRequest(request)) {//判斷是否具備logoutParameterName參數指定的參數,默認參數名稱爲logoutRequest // 若是存在,則在sessionMappingStorage中刪除記錄,並註銷session。 handler.destroySession(request); // 註銷session後,馬上中止執行後面的過濾器 return; } else { log.trace("Ignoring URI " + request.getRequestURI()); } //條件都不知足,繼續執行下面的過濾器 filterChain.doFilter(servletRequest, servletResponse); }
protected ModelAndView handleRequestInternal( final HttpServletRequest request, final HttpServletResponse response) throws Exception { final String ticketGrantingTicketId = this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request); final String service = request.getParameter("service"); if (ticketGrantingTicketId != null) { this.centralAuthenticationService .destroyTicketGrantingTicket(ticketGrantingTicketId); this.ticketGrantingTicketCookieGenerator.removeCookie(response); this.warnCookieGenerator.removeCookie(response); } if (this.followServiceRedirects && service != null) { return new ModelAndView(new RedirectView(service)); } return new ModelAndView(this.logoutView); }
若是直接訪問CAS的logout話,會出現註銷成功頁面,其實大部分狀況下這個頁面是沒有必要的,更多的需求多是退出後顯示登陸頁面,而且登陸成功後仍是會進入到以前的業務系統,
當this.followServiceRedirects && service != null時纔會跳轉到本身指定的view,service應該都比較熟悉了,它是客戶傳的參數,
指定cas中心轉向哪裏,但咱們僅僅傳service 仍是不行的,還須要把followServiceRedirects屬性設爲true,下面看看如何修改這個屬性
那麼能夠修改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
若是出現這種現象:訪問過http://localhost:8080/cas/logout以後不關瀏覽器,仍是能訪問個人應用
可能由於:
1:你的CAS服務器將cookie設置成了瀏覽器有效,那麼表示若是瀏覽器不關閉,則一直有效。
在WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml中設置cookie有效期,默認配置cookie有效期爲-1
2:你的應用中註銷的filter-mapping沒有放在全部mapping以前