当前位置: 代码迷 >> Java相关 >> cas+shiro一致注销原理解析
  详细解决方案

cas+shiro一致注销原理解析

热度:707   发布时间:2016-04-22 19:17:06.0
cas+shiro统一注销原理解析

1,客户端发送一个注销请求到cas server,跟踪casorg.jasig.cas.CentralAuthenticationServiceImpl类的destroyTicketGrantingTicket注销方法,

服务端注销代码

@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发送一个注销请求回来的时候会被接收处理

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过滤前面,所以才会发送这个问题。

  

  相关解决方案