ok,现在开始本文的重点内容讲解,先来了解一下cas 实现single sign out的原理,如图所示:



                                      图一





                                   图二



第一张图演示了单点登陆的工作原理。

第二张图演示了单点登出的工作原理。



从第一张图中,当一个web浏览器登录到应用服务器时,应用服务器(application)会检测用户的session,如果没有session,则应用服务器会把url跳转到CASserver上,要求用户登录,用户登录成功后,CASserver会记请求的application的url和该用户的sessionId(在应用服务器跳转url时,通过参数传给CASserver)。此时在CAS服务器会种下TGC Cookie值到webbrowser.拥有该TGCCookie的webbrowser可以无需登录进入所有建立sso服务的应用服务器application。



在第二张图中,当一个web浏览器要求登退应用服务器,应用服务器(application)会把url跳转到CAS server上的/cas/logout url资源上,



CAS server接受请求后,会检测用户的TCG Cookie,把对应的session清除,同时会找到所有通过该TGCsso登录的应用服务器URL提交请求,所有的回调请求中,包含一个参数logoutRequest,内容格式如下:

<samlp:LogoutRequest ID="[RANDOM ID]" Version="2.0" IssueInstant="[CURRENT DATE/TIME]">

<saml:NameID>@NOT_USED@</saml:NameID>

<samlp:SessionIndex>[SESSION IDENTIFIER]</samlp:SessionIndex>

</samlp:LogoutRequest>

所有收到请求的应用服务器application会解析这个参数,取得sessionId,根据这个Id取得session后,把session删除。

这样就实现单点登出的功能。



知道原理后,下面是结合源代码来讲述一下内部的代码怎么实现的。

首先,要实现single sign out在 应用服务器application端的web.xml要加入以下配置

<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>

31     protected static SessionMappingStorage getSessionMappingStorage() {

32         return SingleSignOutFilter.getSessionMappingStorage();

33     }

34 }

接下来,我们来看一下CAS server端回调是怎么实现的

先来看一下配置,我们知道CASserver所有的用户登录,登出操作,都是由CentralAuthenticationServiceImpl对象来管理。

我们就先把到CentralAuthenticationServiceImpl的spring配置,在applicationContext.xml文件中

<!-- CentralAuthenticationService -->

    <bean id="centralAuthenticationService" class="org.jasig.cas.CentralAuthenticationServiceImpl"

        p:ticketGrantingTicketExpirationPolicy-ref="grantingTicketExpirationPolicy"

        p:serviceTicketExpirationPolicy-ref="serviceTicketExpirationPolicy"

        p:authenticationManager-ref="authenticationManager"

        p:ticketGrantingTicketUniqueTicketIdGenerator-ref="ticketGrantingTicketUniqueIdGenerator"

        p:ticketRegistry-ref="ticketRegistry"

            p:servicesManager-ref="servicesManager"

            p:persistentIdGenerator-ref="persistentIdGenerator"

        p:uniqueTicketIdGeneratorsForService-ref="uniqueIdGeneratorsMap" />

配置使用了spring2.0的xsd。CentralAuthenticationServiceImpl有一个属性叫uniqueTicketIdGeneratorsForService,它是一个map对象

它的key值是所有实现org.jasig.cas.authentication.principal.Service接口的类名,用于保存Principal对象和进行单点登出回调



application server时使用value值为org.jasig.cas.util.DefaultUniqueTicketIdGenerator对象,用于生成唯一的TGCticket。

该属性引用的uniqueIdGeneratorsMap bean在uniqueIdGenerators.xml配置文件中。

<util:map id="uniqueIdGeneratorsMap">

        <entry

            key="org.jasig.cas.authentication.principal.SimpleWebApplicationServiceImpl"

            value-ref="serviceTicketUniqueIdGenerator" />

        <entry

            key="org.jasig.cas.support.openid.authentication.principal.OpenIdService"

            value-ref="serviceTicketUniqueIdGenerator" />

        <entry

            key="org.jasig.cas.authentication.principal.SamlService"

            value-ref="samlServiceTicketUniqueIdGenerator" />

        <entry

            key="org.jasig.cas.authentication.principal.GoogleAccountsService"

            value-ref="serviceTicketUniqueIdGenerator" />

    </util:map>

那CentralAuthenticationServiceImpl是怎么调用的呢?

我们跟踪一下代码,在创建ticket的方法 public StringcreateTicketGrantingTicket(final Credentials credentials)中

可以找到以下这样一段代码:

1         //创建 TicketGrantingTicketImpl 实例

2             final TicketGrantingTicket ticketGrantingTicket = new TicketGrantingTicketImpl(

3                 this.ticketGrantingTicketUniqueTicketIdGenerator

4                     .getNewTicketId(TicketGrantingTicket.PREFIX),

5                 authentication, this.ticketGrantingTicketExpirationPolicy);

6         //并把该对象保存到 ticketRegistry中

7         this.ticketRegistry.addTicket(ticketGrantingTicket);

上面的代码,看到ticketRegistry对象保存了创建的TicketGrantingTicketImpl对象,下面我们看一下当ticket销毁的时候,会做什么

事情,代码如下:

 1     public void destroyTicketGrantingTicket(final String ticketGrantingTicketId) {

 2         Assert.notNull(ticketGrantingTicketId);

 3 

 4         if (log.isDebugEnabled()) {

 5             log.debug("Removing ticket [" + ticketGrantingTicketId

 6                 + "] from registry.");

 7         }

 8     //从 ticketRegistry对象中,取得TicketGrantingTicket对象

 9         final TicketGrantingTicket ticket = (TicketGrantingTicket) this.ticketRegistry

10             .getTicket(ticketGrantingTicketId, TicketGrantingTicket.class);

11 

12         if (ticket == null) {

13             return;

14         }

15 

16         if (log.isDebugEnabled()) {

17             log.debug("Ticket found.  Expiring and then deleting.");

18         }

19         ticket.expire();//调用expire()方法,让ticket过期失效

20         this.ticketRegistry.deleteTicket(ticketGrantingTicketId);//从ticketRegistry中删除的ticket 对象

21     }

我们看到,它是从ticketRegistry对象中取得TicketGrantingTicket对象后,调用expire方法。接下来,要关心的就是expire方法做什么事情

 1     public synchronized void expire() {

 2         this.expired.set(true);

 3         logOutOfServices();

 4     }

 5 

 6     private void logOutOfServices() {

 7         for (final Entry<String, Service> entry : this.services.entrySet()) {

 8             entry.getValue().logOutOfService(entry.getKey());

 9         }

10     }

从代码可以看到,它是遍历每个 Service对象,并执行logOutOfService方法,参数是StringsessionIdentifier

现在我们可以对应中,它存放的Service就是在uniqueIdGeneratorsMap bean定义中的那些实现类



因为logOutOfService方法的实现,所有实现类都是由它们继承的抽象类AbstractWebApplicationService来实现,我们来看一下

AbstractWebApplicationService的logOutOfService方法,就可以最终找出,实现singlesign out的真正实现代码,下面是主要代码片段:

 1   public synchronized boolean logOutOfService(final String sessionIdentifier) {

 2         if (this.loggedOutAlready) {

 3             return true;

 4         }

 5 

 6         LOG.debug("Sending logout request for: " + getId());

 7         //组装 logoutRequest参数内容

 8         final String logoutRequest = "<samlp:LogoutRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\""

 9             + GENERATOR.getNewTicketId("LR")

10             + "\" Version=\"2.0\" IssueInstant=\"" + SamlUtils.getCurrentDateAndTime()

11             + "\"><saml:NameID 

12 

13 xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">@NOT_USED@</saml:NameID><samlp:SessionIndex>"

14             + sessionIdentifier + "</samlp:SessionIndex></samlp:LogoutRequest>";

15         

16         this.loggedOutAlready = true;

17         //回调所有的application,getOriginalUrl()是取得回调的application url

18         if (this.httpClient != null) {

19             return this.httpClient.sendMessageToEndPoint(getOriginalUrl(), logoutRequest);

20         }

21         

22         return false;

23     }

至此,已经通过源代码把 CAS实现 single signout的实现原理和方法完整叙述了一遍,希望对CAS感兴趣的朋友有所帮忙,

单点登录之CAS简单介绍的更多相关文章

  1. CAS单点登录(一):单点登录与CAS理论介绍

    一.什么是单点登录(SSO) 单点登录主要用于多系统集成,即在多个系统中,用户只需要到一个中央服务器登录一次即可访问这些系统中的任何一个,无须多次登录. 单点登录(Single Sign On),简称 ...

  2. java单点登录系统CAS的简单使用

    转:http://blog.csdn.net/yunye114105/article/details/7997041 背景 有几个相对独立的java的web应用系统, 各自有自己的登陆验证功能,用户在 ...

  3. SSO单点登录Spring-Security & CAS使用手册

    1.1概述 1.1.1单点登录介绍 单点登录(Single Sign On , 简称 SSO )是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户只需要登录一次就可 ...

  4. 单点登录系统CAS筹建及取得更多用户信息的实现

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  5. asp.net项目与开源单点登录项目CAS的结合

    这段时间搞的一个asp.net mvc项目,采用了单点登录. 这个单点登录就是CAS,一个开源的JAVA项目.当然,这并不影响ASP.NET项目结合它来进行登录.因为各自分工不同:单点登录(管它是不是 ...

  6. 单点登录之CAS原理和实现(转载)

    转载源:https://www.jianshu.com/p/613c615b7ef1 单点登录之CAS原理和实现 来源于作者刘欣的<码农翻身> + 自己的备注理解 这家集团公司财大气粗,竟 ...

  7. 单点登录(二)----实战------简单搭建CAS---测试认证方式搭建CAS

    我们在上一篇文章中已经介绍了cas以及它的工作流程. 单点登录(一)-----理论-----单点登录SSO的介绍和CAS+选型 本章我们开始动手搭建一个完整的cas服务实现2个web之间的单点登录. ...

  8. SpringBoot集成CAS单点登录,SSO单点登录,CAS单点登录(视频资料分享篇)

    单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. 很早期的公司 ...

  9. 单点登录实现----CAS(一)

    最近我们部门交接了一个新项目--- passport,即我司的单点登录系统,虽然没有交接给我,但是个人觉得登录技术是个很好的知识,于是就忙里偷闲简单地学习了下. 单点登录SSO(single sign ...

  10. java单点登录原理与简单实现

    一.单系统登录机制 1.http无状态协议 web应用采用browser/server架构,http作为通信协议.http是无状态协议,浏览器的每一次请求,服务器会独立处理,不与之前或之后的请求产生关 ...

随机推荐

  1. (python)学习ing||类学习,@property装饰器

    class pers(): def __init__(self,hp): self._hp=hp @property def hp(self): return self._hp @hp.setter ...

  2. 案例:OGG目标端进程ABENDED处理

    源端环境:RHEL 6.5 + Oracle 11.2.0.4 RAC + OGG 19.1.0.0.4 目标端环境:RHEL 7.6 + Oracle 19.3 + OGG 19.1.0.0.4 故 ...

  3. DbgridEh表格框的【可连续点击两次编辑设置,和不允许点击两次编辑的设置】

  4. 【Flink入门修炼】1-3 Flink WordCount 入门实现

    本篇文章将带大家运行 Flink 最简单的程序 WordCount.先实践后理论,对其基本输入输出.编程代码有初步了解,后续篇章再对 Flink 的各种概念和架构进行介绍. 下面将从创建项目开始,介绍 ...

  5. UVA1108 Mining Your Own Business 题解

    题目传送门 题意 在一个无向图上选择尽量少的点涂黑,使得删除任意一个点后,每个连通分量里都至少有一个黑点(多组数据). 正文 观察题意,发现这是个 Tarjan 求点双连通分量的板子. 考虑在求点双连 ...

  6. JS Leetcode 80. 删除有序数组中的重复项 II题解,常规解法与快慢双指针做法

    壹 ❀ 引 今天的题目来自LeetCode80. 删除有序数组中的重复项 II,是一道难度中等,但实际挺简单的一道题,题目描述如下: 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每 ...

  7. NC20189 [JSOI2011]分特产

    题目链接 题目 题目描述 JYY 带队参加了若干场ACM/ICPC 比赛,带回了许多土特产,要分给实验室的同学们. JYY 想知道,把这些特产分给N 个同学,一共有多少种不同的分法? 当然,JYY 不 ...

  8. 【framework】应用进程启动流程

    1 前言 Activity启动流程 中介绍了从点击桌面上应用快捷方式到 Activity 的 onCreate() 方法调用流程,本将介绍应用进程的启动流程.由于应用进程启动流程复杂,本文按进程将其拆 ...

  9. 【OpenGL ES】绘制立方体

    1 前言 ​ 本文主要介绍使用 OpenGL ES 绘制立方体,读者如果对 OpenGL ES 不太熟悉,请回顾以下内容: 绘制三角形 绘制彩色三角形 绘制正方形 绘制圆形 ​ 在绘制立方体的过程中, ...

  10. 实例详解在Go中构建流数据pipeline

    本文分享自华为云社区<Go并发范式 流水线和优雅退出 Pipeline 与 Cancellation>,作者:张俭. 介绍 Go 的并发原语可以轻松构建流数据管道,从而高效利用 I/O 和 ...