1,客戶端發送一個註銷請求到cas server,跟蹤casorg.jasig.cas.CentralAuthenticationServiceImpl類的destroyTicketGrantingTicket註銷方法,web
服務端註銷代碼session
@Audit( action="TICKET_GRANTING_TICKET_DESTROYED", actionResolverName="DESTROY_TICKET_GRANTING_TICKET_RESOLVER", resourceResolverName="DESTROY_TICKET_GRANTING_TICKET_RESOURCE_RESOLVER") @Profiled(tag = "DESTROY_TICKET_GRANTING_TICKET", logFailuresSeparately = false) @Transactional(readOnly = false) @Override public List<LogoutRequest> destroyTicketGrantingTicket(final String ticketGrantingTicketId) { Assert.notNull(ticketGrantingTicketId); logger.debug("Removing ticket [{}] from registry.", ticketGrantingTicketId); final TicketGrantingTicket ticket = this.ticketRegistry.getTicket(ticketGrantingTicketId, TicketGrantingTicket.class); if (ticket == null) { logger.debug("TicketGrantingTicket [{}] cannot be found in the ticket registry.", ticketGrantingTicketId); return Collections.emptyList(); } logger.debug("Ticket found. Processing logout requests and then deleting the ticket...");
//在這裏cas server會去根據客戶端帶過來的ticket找到全部在cas server服務註冊過的cas client server,讓後對這些客戶端服務發送一個http請求,客戶端接受請求,刪除//自己的ticket及註銷session,cas server發送請求看下一段代碼 final List<LogoutRequest> logoutRequests = logoutManager.performLogout(ticket); this.ticketRegistry.deleteTicket(ticketGrantingTicketId); return logoutRequests; }
@Override
public List<LogoutRequest> performLogout(final TicketGrantingTicket ticket) { final Map<String, Service> services; // synchronize the retrieval of the services and their cleaning for the TGT // to avoid concurrent logout mess ups synchronized (ticket) { services = ticket.getServices(); ticket.removeAllServices(); } ticket.markTicketExpired(); final List<LogoutRequest> logoutRequests = new ArrayList<LogoutRequest>(); // if SLO is not disabled if (!disableSingleSignOut) { // through all services
//循環遍歷客戶端的server for (final String ticketId : services.keySet()) { final Service service = services.get(ticketId); // it's a SingleLogoutService, else ignore if (service instanceof SingleLogoutService) { final SingleLogoutService singleLogoutService = (SingleLogoutService) service; // the logout has not performed already if (!singleLogoutService.isLoggedOutAlready()) { final LogoutRequest logoutRequest = new LogoutRequest(ticketId, singleLogoutService); // always add the logout request logoutRequests.add(logoutRequest); final RegisteredService registeredService = servicesManager.findServiceBy(service); // the service is no more defined, or the logout type is not defined or is back channel if (registeredService == null || registeredService.getLogoutType() == null || registeredService.getLogoutType() == LogoutType.BACK_CHANNEL) { // perform back channel logout
//向客戶端發送一個請求, if (performBackChannelLogout(logoutRequest)) { logoutRequest.setStatus(LogoutRequestStatus.SUCCESS); } else { logoutRequest.setStatus(LogoutRequestStatus.FAILURE); LOGGER.warn("Logout message not sent to [{}]; Continuing processing...", singleLogoutService.getId()); } } } } } } return logoutRequests; }
下面在來看一下客戶端接收的代碼,客戶段單點註銷必須配置SingleSignOutFilter,前文cas server發送一個註銷請求回來的時候會被接收處理app
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) servletRequest; //重點的兩個IF判斷,同時也是邏輯處理,第一是判斷是否是第一次登陸的時候會進入方法往cas SessionMappingStorage的添加ticket,sessionId鍵值對 if (handler.isTokenRequest(request)) { LOG.warn("第{}次進來映射,sessionId={}", index++, request.getSession().getId()); handler.recordSession(request);
//判斷是不是註銷請求,若是是註銷請求進入邏輯,註銷session同時刪除SessionMappingStorage的鍵值對(就是這裏實現了統一註銷) } else if (handler.isLogoutRequest(request)) { LOG.warn("第{}進來刪除映射,sessionId={}", removeIndex++, request.getSession().getId()); handler.destroySession(request); // Do not continue up filter chain return; } else { log.trace("Ignoring URI " + request.getRequestURI()); } filterChain.doFilter(servletRequest, servletResponse); }
/jaxws/services/**=anon個人shiro配置了web service不進行身份驗證也是無效的,由於SingleSignOutFilter過濾器的優先級在shiro過濾前面,因此纔會發送這個問題。ide