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过滤前面,所以才会发送这个问题。
cas+shiro统一注销原理解析的更多相关文章
- Spring MVC源码(四) ----- 统一异常处理原理解析
		
SpringMVC除了对请求URL的路由处理特别方便外,还支持对异常的统一处理机制,可以对业务操作时抛出的异常,unchecked异常以及状态码的异常进行统一处理.SpringMVC既提供简单的配置类 ...
 - Java并发包JUC核心原理解析
		
CS-LogN思维导图:记录CS基础 面试题 开源地址:https://github.com/FISHers6/CS-LogN JUC 分类 线程管理 线程池相关类 Executor.Executor ...
 - 从零开始实现lmax-Disruptor队列(四)多线程生产者MultiProducerSequencer原理解析
		
MyDisruptor V4版本介绍 在v3版本的MyDisruptor实现多线程消费者后.按照计划,v4版本的MyDisruptor需要支持线程安全的多线程生产者功能. 由于该文属于系列博客的一部分 ...
 - 从零开始实现lmax-Disruptor队列(六)Disruptor 解决伪共享、消费者优雅停止实现原理解析
		
MyDisruptor V6版本介绍 在v5版本的MyDisruptor实现DSL风格的API后.按照计划,v6版本的MyDisruptor作为最后一个版本,需要对MyDisruptor进行最终的一些 ...
 - jdk线程池ThreadPoolExecutor工作原理解析(自己动手实现线程池)(一)
		
jdk线程池ThreadPoolExecutor工作原理解析(自己动手实现线程池)(一) 线程池介绍 在日常开发中经常会遇到需要使用其它线程将大量任务异步处理的场景(异步化以及提升系统的吞吐量),而在 ...
 - cas+shiro实现不时时的去请求cas进行身份验证
		
cas+shiro不进行时时去cas验证身份信息,需要用shiro在当前系统有一份完整的认证机构. 那么有一个问题,什么时候去cas校验信息,目前的配置方式: cas系统设置默认的浏览器session ...
 - Android中插件开发篇之----应用换肤原理解析
		
一.前言 今天又到周末了,感觉时间过的很快呀.又要写blog了.那么今天就来看看应用的换肤原理解析.在之前的一篇博客中我说道了Android中的插件开发篇的基础:类加载器的相关知识.没看过的同学可以转 ...
 - Nginx 原理解析和配置摘要
		
前言 Nginx 作为高性能的 http 服务器,知名度不必多言,相似产品中无出其右.本篇随笔记录我认为较为重要的原理和配置. 1. 原理解析 1.1 结构 以上是 Nginx 的结构图,其包含一个 ...
 - 基于OpenCV进行图像拼接原理解析和编码实现(提纲 代码和具体内容在课件中)
		
一.背景 1.1概念定义 我们这里想要实现的图像拼接,既不是如题图1和2这样的"图片艺术拼接",也不是如图3这样的"显示拼接",而是实现类似"BaiD ...
 
随机推荐
- (引用)Python 元素、元组、列表、字典的区别
			
转载:http://www.th7.cn/Program/Python/201407/231060.shtml 元素: 元组:tuple=('nice','to','meet','you') 列表:l ...
 - 查询AD账号的SID
			
在非域控的计算机上可以查询所用AD用户的SID,不过现成的工具不能直接实现此目的,我们需要在这些计算机上安装RSAT(远程服务器管理工具),然后使用dsquery和dsget命令,来快速查询AD用户的 ...
 - oracle启动脚本 .
			
.#!/bin/bash set -x su -oracle >>EON lsnrctl start sqlplus /nolog >>EOF conn / as sy ...
 - Java重点之小白解析--浅谈数据流形式图片上载
			
文档上载,上载也不知道哪个大神(混球)起的名字,读起来怪怪的,反正平时我只读上传. 闲话少说,直入主题.先等等这两天做文件上传,都快把宝宝折磨疯了,不会呀,各种查呀,最可悲的是废了老大功夫学会了传送文 ...
 - 反射,System.Type类
			
http://m.blog.csdn.net/blog/woddle/40623333 两个现实中的例子:1.B超:大家体检的时候大概都做过B超吧,B超可以透过肚皮探测到你内脏的生理情况.这是如何做到 ...
 - C#图片压缩处理算法
			
原文链接:http://blog.csdn.net/szstephenzhou/article/details/38900345
 - C#实现自动单击
			
最新玩了一下上学时候玩的游戏,但游戏里面变化太多了,进去后等级就很高,要不停地点击鼠标加技能. 所以利用工作中常用的C#调用 API不停地点击鼠标. 如图: 为方便在基础上修改,我把整个解决方案放到百 ...
 - 刨一刨内核container_of()的设计精髓
			
新年第一帖,总得拿出点干货才行,虽然这篇水分还是有点大,大家可以晒干了温水冲服.这段时间一直在整理内核学习的基础知识点,期间又碰到了container_of()这个宏,当然还包括一个叫做offseto ...
 - MySQL pdo预处理能防止sql注入的原因
			
MySQL pdo预处理能防止sql注入的原因: 1.先看预处理的语法 $pdo->prepare('select * from biao1 where id=:id'); $pdo->e ...
 - python操作系统环境变量
			
获取整个系统变量的方法是os.environ,这是一个os的class类型,使用的时候可以转换为字典类型 environ_value = dict(os.environ) 这样就可以看所有的key,e ...