第1章 背景
目前SaCa DataViz 与应用系统间推荐的集成方式是使用第三方单点登录系统进行单点登录集成,而Apereo CAS是目前Java服务器环境下使用最为广泛的单点登录系统。基于此情况,本文对Apereo CAS 单点登录系统的基本使用进行一些基本介绍,以方便不了解Apereo CAS的项目开发人员上手搭建Apereo CAS单点登录,利用CAS实现应用系统与SaCa DataViz的单点登录集成。
本文基于目前SaCa DataViz项目组的使用经验并参考网站资料编写而成,由于CAS发展多年,可配置内容非常多,本文仅会包含Apereo CAS系统的基本配置使用作为使用CAS的基础,并涉及少量原理性内容。对于本文没有涉及的使用方法及使用方式,请参考Apereo CAS 在GitHub上的文档: https://apereo.github.io/cas 或参考网上其他人编写的资料。
第2章 CAS介绍
2.1 CAS版本
CAS 全称是Central Authentication Service(中心认证服务),它是一个单点登录(Single-Sign-On)协议,Apereo CAS是实现该协议的软件包。
CAS最初由Yale大学的Shawn Bayern开发实现,随后由Yale大学的Drew Mazurek负责维护,此时的CAS被称作 Yale CAS 。2004年,CAS成为了JASIG(Java in Administration Special Interest Group) 的一个项目,2008年起开始由JASIG负责CAS的维护,CAS被改称 JASIG CAS 。2012年,JASIG与Sakai Foundation合并为Apereo Foundation,此后CAS称为 Apereo CAS 。
CAS协议版本有3个版本,1.0,2.0和3.0。而Apereo CAS软件截至2018年11月底最新版本是5.3.6,支持CAS 3.0版本协议及其他SAML(部分支持)、OAuth等一些其他单点登录协议。
目前SaCa DataViz可以支持 Apereo CAS 3.5(2015年)以上版本(更低版本理论上也可以支持,但年代过早不推荐使用),文档后续将基于 Apereo CAS 4.1.0版本进行说明。
2.2 CAS基本概念
2.2.1 总体运行过程
CAS 单点登录系统中,分为两方,一方为Apereo CAS服务端提供单点登录服务,一方为应用端作为CAS的客户端使用单点登录服务。
上图为CAS官网上的架构图(未包含浏览器端)。
在未采用单点登录前,用户登录在各自的应用端,每次访问应用均需要在各自应用上登录。
在采用CAS单点登录后,登录页在CAS服务端提供,CAS服务端负责读取用户信息进行登录认证,认证成功后,CAS服务会在会话(Session)中记录CAS登录信息。CAS客户端应用在需要登录时,自动从CAS服务端安全获取到当前登录人,完成登录,并使用应用的会话(Session)记录当前登录信息。
登录过程可以由应用端(CAS客户端)发起,也可以直接访问CAS服务端发起。当由应用端发起时(例如用户访问了一个应用中需要登录认证的请求),会通过页面跳转方式跳转到CAS服务端(此时会有发起端的标识),待用户在CAS服务端认证成功后,页面自动跳回到原请求的应用端通知应用端获取登录人信息完成登录。
2.2.2 特点
CAS标准的单点登录使用过程具有如下特点:
分为两端:CAS认证服务端、CAS客户端(应用),用户认证及登录发生在CAS端;
发起者可以是CAS服务端,也可以是应用端;
CAS服务端与应用端各自保存认证后的结果到会话;
登录时会发生应用与CAS间的页面跳转;
应用端需要与CAS端直接通信,应用端会通过服务器后台通信访问CAS端进行验证。
第3章 CAS基本使用
由于CAS集成后,所有应用的登录都需要在CAS端(包含用户的认证、登录界面的自定义),因此除了示例系统,正式的CAS集成总是会需要进行CAS端的开发构建。
一般来说,可能需要开发的内容有几个方面:
1.登录界面
2.新的认证方式,如加密的登录密码
3.自定义认证成功后向客户端返回的信息,默认的实现是登录名
4.自定义的CAS客户端维护
构建CAS有几种方式:
1.下载打包好的war包,解压后,手动修改配置,二次开发的Java代码另行构建打包,手动放在部署的应用的WEB-INF/lib中;
2.下载CAS完整代码,修改代码和配置打包部署(官方不推荐);
3.官方推荐的WAR包Overlay方式。该方式需要使用maven或Gradle构建工具,在工程中依赖完整CAS war包,并在工程中手动添加需要修改的配置文件、页面或实现类,然后使用工具构建自动合并生成部署的war包。
第一种方式操作简单,但需要维护应用配置、Java代码并手动合并,且Java代码依赖也不易手动维护,因此这里说一下第三种方式。(第一种操作与一般应用开发部署类似,不再赘述)
3.1 下载WAR包
如果使用第一种方式,可以从maven网站下载所有版本的war包:
5.0之前的版本:
http://repo1.maven.org/maven2/org/jasig/cas/cas-server-webapp/
5.0之后的版本:
http://repo1.maven.org/maven2/org/apereo/cas/cas-server-webapp
使用War Overlay方式也需要一个war包,可以手动从该地址下载,也可以直接在工程构建时从gradle或maven下载后的本地库中获取。
3.2 Gradle WAR Overlay
这里介绍一个使用Gradle进行WAR Overlay开发构建的方法。
- Gradle:根据自己部署使用的JDK版本,推荐使用2.14.1或以上版本(下载位于https://www.gradle.org),下载后解压到某一路径下即可。
- Eclipse Gradle插件:可以使用Gradle STS Integration for Eclipse插件(可于Eclipse Marketplace中搜索Gradle IDE Pack下载安装,或添加 http://www.nodeclipse.org/updates/gradle-ide-pack/ update site安装下载)。安装后,需要在Gradle(STS)的 Gradle Distribution中指定 Gradle解压后的位置
安装完成后,创建两个Java工程,分别对应war overlay工程和Java扩展工程。在两个工程中根目录下分别创建build.gradle,并在war overlay工程中创建settings.gradle,作为Gradle根项目引用另外的扩展工程。war overlay工程的build.gradle中需要应用 scaldingspoon.gradle.WarOverlayPlugin插件,并依赖另外的java 扩展工程。
build.gradle和 settings.gradle配置好后,将两个工程转为Gradle STS工程即可。
3.3 一个可登录的CAS
这里示例一个使用关系数据库中的用户名和密码登录的CAS服务器的配置和构建(不涉及二次开发)。如果使用war包下载维护的方式开发可以直接跳到3.3.2节配置部分。
3.3.1 工程结构
按照上述Gradle War Overlay方式建立两个gradle工程,工程结构如下所示:
sso-cas-extension/build.gradle 内容:
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
project.ext {
casVersion = '4.1.0'
}
compileJava {
options.encoding = 'utf-8'
}
dependencies {
compile 'javax.servlet:servlet-api:2.5'
compile 'org.springframework.security:spring-security-core:4.0.1.RELEASE'
compile group: 'org.jasig.cas', name: 'cas-server-core-api', version: casVersion
compile group: 'org.jasig.cas', name: 'cas-server-webapp-support', version: casVersion
}
repositories {
mavenCentral()
}
eclipse {
classpath {
downloadSources = true
downloadJavadoc = false
}
wtp {
facet {
facet name: 'jst.utility', version : '1.0'
}
}
}
sso-cas-overlay/build.gradle 内容(这里以连接mysql为例):
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
apply plugin: 'war'
apply plugin: scaldingspoon.gradle.WarOverlayPlugin
project.ext {
casVersion = '4.1.0'
}
compileJava {
options.encoding = 'utf-8'
}
dependencies {
providedCompile 'javax.servlet:servlet-api:2.5'
runtime("org.jasig.cas:cas-server-webapp:${casVersion}@war") {
transitive = true // setting this to true calculates transitive dependencies for addition to the target WAR
}
runtime "mysql:mysql-connector-java:5.1.38" // JDBC Driver
runtime project(':sso-cas-extension')
}
repositories {
mavenCentral()
}
warOverlay {
includeWarJars false // whether to include the jar files in the WAR. Default is false. If false, it might be useful to set transitive to `true` for the WAR dependency so its dependencies will be calculated and added
}
eclipse {
classpath {
downloadSources = true
downloadJavadoc = false
}
wtp {
facet {
facet name: 'jst.utility', version : '1.0'
}
}
}
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "org.scaldingspoon.gradle:gradle-waroverlay-plugin:0.9.3"
}
}
sso-cas-overlay/settings.gradle 内容:
includeFlat 'sso-cas-extension'
工程结构中,sso-cas-overlay/src/main/webapp 下存放的是CAS应用中需要修改或添加的配置及页面等内容,sso-cas-extension/src/main/java 下存放的是后续扩展所需的Java类代码(本示例中不会使用)。
3.3.2 配置修改
为了使这个基本的CAS服务能够运行起来,我们需要在工程中添加修改一些配置。这些配置文件来自CAS WAR包,将这些配置文件拷贝到与原始位置相同的相对路径下,然后修改编辑文件的内容。
基础配置
涉及的配置文件:WEB-INF/cas.properties。
WEB-INF/cas.properties是CAS的重要配置文件,包含了众多properties配置。
WEB-INF/cas.properties 的前两个配置项server.name配置为CAS服务的访问地址(无路径)、server.prefix配置应用访问路径。
配置数据库用户名/密码认证
涉及的配置文件:WEB-INF/deployerConfigContext.xml, WEB-INF/cas.properties
WEB-INF/deployerConfigContext.xml 包含了CAS部署所需的一些常用配置。对该文件进行以下修改:
删除或注释掉bean
id="proxyPrincipalResolver"
删除或注释掉bean
id="authenticationManager"
中 map的两项 entry添加bean
id="basicPrincipalResolver"
:<bean id="basicPrincipalResolver" class="org.jasig.cas.authentication.principal.BasicPrincipalResolver" />
添加bean
id="dataSource"
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" p:driverClass="${database.driverClass}" p:jdbcUrl="${database.url}" p:user="${database.user}" p:password="${database.password}" p:initialPoolSize="${database.pool.minSize}" p:minPoolSize="${database.pool.minSize}" p:maxPoolSize="${database.pool.maxSize}" p:maxIdleTimeExcessConnections="${database.pool.maxIdleTime}" p:checkoutTimeout="${database.pool.maxWait}" p:acquireIncrement="${database.pool.acquireIncrement}" p:acquireRetryAttempts="${database.pool.acquireRetryAttempts}" p:acquireRetryDelay="${database.pool.acquireRetryDelay}" p:idleConnectionTestPeriod="${database.pool.idleConnectionTestPeriod}" p:preferredTestQuery="${database.pool.connectionHealthQuery}" />
添加bean id=" dbAuthHandler",需要将查询用户密码的SQL放在p:sql属性中,类似如下形式:select login_pass from userlogin where login_name=?
<bean id="dbAuthHandler" class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler" p:dataSource-ref="dataSource" p:sql="<SQL HERE>" />
添加bean id="authenticationManager" map中的entry:
<entry key-ref="dbAuthHandler" value-ref="basicPrincipalResolver" />
修改 cas.properties,添加用户信息所在的数据库配置,驱动、url、用户名及密码需要手动填写:
# == Basic database connection pool configuration ==
database.driverClass=
database.url=
database.user=
database.password=
database.pool.minSize=6
database.pool.maxSize=18
# Maximum amount of time to wait in ms for a connection to become
# available when the pool is exhausted
database.pool.maxWait=10000
# Amount of time in seconds after which idle connections
# in excess of minimum size are pruned.
database.pool.maxIdleTime=120
# Number of connections to obtain on pool exhaustion condition.
# The maximum pool size is always respected when acquiring
# new connections.
database.pool.acquireIncrement=6
# == Connection testing settings ==
# Period in s at which a health query will be issued on idle
# connections to determine connection liveliness.
database.pool.idleConnectionTestPeriod=30
# Query executed periodically to test health
database.pool.connectionHealthQuery=select 1
# == Database recovery settings ==
# Number of times to retry acquiring a _new_ connection
# when an error is encountered during acquisition.
database.pool.acquireRetryAttempts=5
# Amount of time in ms to wait between successive aquire retry attempts.
database.pool.acquireRetryDelay=2000
按上述配置完成后,可以使用用户名及密码登录,密码使用明文,登录成功后,客户端将获得登录时的登录名。
https、http配置
CAS默认配置下,所有的请求(浏览器请求及CAS客户端发来的验证请求)都是需要使用https配置SSL/TLS证书使用。对于公网浏览器登录请求,可以应该使用CA签发的证书,自签名证书浏览器会出现警告;对于客户端验证请求,内部应用通常会使用内网地址,此时可以用自签名证书,但需要将生成的证书添加到JRE的cacerts中。
如果不想使用https则需要一些配置,则需要修改一些配置,不使用https的情况下,CAS默认的登录页会出现一个警告。
- WEB-INF/web.xml 查找
<security-constraint>
标签,去掉该项内容; - WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml 查找
p:cookieSecure
,将该值设为false。
- WEB-INF/web.xml 查找
3.3.3 构建部署
对于直接修改war包的方式不需要单独构建,可直接于tomcat下运行。
使用war overlay方式执行工具的构建命令生成war包(Java扩展的代码会被自动单独打成jar),将其放到tomcat webapps下作为web应用运行。
直接访问该应用会弹出登录页,登录成功后会跳转到登录成功提示页。
3.4 后续的开发
这里提供一些后续二次开发可能会用到的其他提示,更多信息可以在网站上查找资料了解。
3.4.1 数据库加密密码的认证
CAS本身还提供了org.jasig.cas.adaptors.jdbc.QueryAndEncodeDatabaseAuthenticationHandler
对密码进行加密,但用法与原配置的QueryDatabaseAuthenticationHandler
用法有所不同。
对于已有的密码存储如果有自己的加密方式,也可以手动继承org.jasig.cas.adaptors.jdbc.AbstractJdbcUsernamePasswordAuthenticationHandler
实现自己的用户名密码验证。
修改后需要修改deployerConfigContext.xml。
3.4.2 返回客户端的认证信息
CAS内置的BasicPrincipalResolver
会使用登录名返回到客户端应用,如果需要返回其他标识则可以自行实现org.jasig.cas.authentication.principal.PrincipalResolver
接口,并配置在deployerConfigContext.xml的authenticationManager中。
3.4.3 页面自定义
CAS服务端使用spring webflow处理cas协议及页面显示。
WebFlow的配置位于WEB-INF/webflow下,下面包含了每个流程的配置,这些配置在不添加登录方式的情况下可以不用修改。
页面模板位于WEB-INF/view/jsp下,default为默认主题的ui页面,default/ui/LoginView.jsp为默认登录页。
第4章 CAS客户端集成
4.1 客户端应用信息
所有的CAS客户端应用默认情况下都需要在CAS服务端注册一些信息才能够对接CAS,这样能够保证用户信息安全性。
CAS 4.1.0版本默认的注册方式是在CAS WEB-INF/classes/services下使用json文件注册。每个文件对应一个客户端,其内容大致如下:
{
"@class" : "org.jasig.cas.services.RegexRegisteredService",
"id" : 18,
"description" : "xxx应用",
"serviceId" : "http://www.sacadataviz.com/dataviz-service/.*",
"name" : "analysis service",
"accessStrategy" : {
"@class" : "org.jasig.cas.services.DefaultRegisteredServiceAccessStrategy",
"enabled" : true,
"ssoEnabled" : true
},
"evaluationOrder" : 1003,
"usernameAttributeProvider" : {
"@class" : "org.jasig.cas.services.DefaultRegisteredServiceUsernameProvider"
},
"attributeReleasePolicy" : {
"@class" : "org.jasig.cas.services.ReturnAllAttributeReleasePolicy"
},
"logoutType" : "BACK_CHANNEL"
}
其中,
id是唯一标识数字,不能重复
serviceId是客户端应用的标识地址,会由URL中service参数传递过来的地址进行匹配,只要匹配了该地址即可以按照该应用身份进行处理。可以使用应用一级地址的通配符标识。
name及description是名称和描述信息
enabled和ssoEnabled需要设置为
true
,才能够通过该应用的认证请求。logoutType 用于处理单点登出(SLO),默认BACK_CHANNEL使用后端登出(CAS服务端向客户端应用发SLO登出请求),FRONT_CHANNEL使用前端登出(取决于CAS版本,通过HTTP 302跳转或JSONP Ajax请求),设置为NONE则不使用单点登出。
另外CAS也提供了一个独立的CAS管理应用以图形方式管理CAS的客户端应用,可以参考https://apereo.github.io/cas-management 进行安装使用,本文不做详述。
如果以上的方式不能满足需求,则需要进行手动扩展。
4.2 基于Spring-Security的应用集成
CAS本身提供了Java客户端,Spring Security 也提供了CAS单点登录支持,因此两者可以较容易地集成在一起。(DataViz就是采用的这种集成方式)
在使用了Spring Security的应用中,需要依赖以下两个组件(以4.0.1版本SpringSecurity为例):
org.springframework.security:spring-security-cas:4.0.1.RELEASE
org.jasig.cas.client:cas-client-core:3.4.1
建议使用Maven或Gradle完成依赖Jar包的引入。
此后,通常可以按以下思路完成:
添加并设置一个UserDetailsService实现,完成将CAS返回的登录人构建为UserDetails。
添加Service Properties
<beans:bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<beans:property name="service" value="${sso.cas.localServer}${sso.cas.localServicePath}" />
<beans:property name="sendRenew" value="false" />
</beans:bean>
- 添加CasEntryPoint
<beans:bean id="casEntryPoint"
class=" org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<beans:property name="loginUrl" value="${sso.cas.casServer}/login" />
<beans:property name="serviceProperties" ref="serviceProperties" />
</beans:bean>
- 添加CasFilter
<beans:bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="authenticationSuccessHandler">
<beans:bean
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="${sso.cas.defaultTargetRedirect}" />
<beans:property name="targetUrlParameter" value="target" />
</beans:bean>
</beans:property>
</beans:bean>
- 添加CasAuthenticationProvider(UserDetailsService bean id为 userDetailService,${sso.cas.casValidateServer}为CAS服务的内网地址)
<beans:bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<beans:property name="authenticationUserDetailsService">
<beans:bean
class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<beans:constructor-arg ref="userDetailService" />
</beans:bean>
</beans:property>
<beans:property name="serviceProperties" ref="serviceProperties" />
<beans:property name="ticketValidator">
<beans:bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<!-- server URL prefix -->
<beans:constructor-arg index="0" value="${sso.cas.casValidateServer}" />
</beans:bean>
</beans:property>
<beans:property name="key" value="bonjour!" />
</beans:bean>
- 添加登出Filter
<!-- This filter handles a Single Logout Request from the CAS Server -->
<beans:bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter">
<beans:property name="casServerUrlPrefix" value="${sso.cas.casServer}" />
</beans:bean>
<!-- This filter redirects to the CAS Server to signal Single Logout should be performed -->
<beans:bean id="requestSingleLogoutFilter"
class="org.springframework.security.web.authentication.logout.LogoutFilter">
<beans:constructor-arg value="${sso.cas.casServer}/logout?service=${sso.cas.localServer}"/>
<beans:constructor-arg>
<beans:bean class=
"org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</beans:constructor-arg>
<beans:property name="filterProcessesUrl" value="${sso.cas.localLogoutPath}"/>
</beans:bean>
- 将添加的Filter添加到spring security过滤器中,该内容位于http标签下
<custom-filter position="CAS_FILTER" ref="casFilter" />
<custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
<custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
- 添加CasAuthenticationProvider到authenticationManager中
<authentication-manager alias="authenticationManager">
<authentication-provider ref="casAuthenticationProvider" />
</authentication-manager>
以上所有使用${…}变量的地方,都需要用实际值替换或使用properties文件注入。
sso.cas.casServer=
sso.cas.localServer=
sso.cas.casValidateServer=
sso.cas.defaultTargetRedirect=
sso.cas.localServicePath=/login/cas
sso.cas.localLogoutPath=/logout/cas
4.3 不使用Spring-Security的Java Web应用集成
不使用Spring-Security的情况下意味着需要手动完成CAS协议的认证过程,认证过程可以使用CAS提供的客户端 (org.jasig.cas.client:cas-client-core:3.4.1)。
由于不同应用系统的用户实现及管理的方式都不同,这里仅给出一些利用CAS客户端实现CAS协议登录、登出的基本方法。
4.3.1 登录
典型的由Web应用端发起的CAS登录过程包含几个部分:
未登录请求的拦截和登录跳转
CAS登录认证
接收CAS认证结果ticket,验证ticket并获取用户信息
将CAS获取到的用户信息转为系统登录会话信息,完成登录状态。
这几个部分中,第2部分是由本身CAS服务完成的,不涉及集成;第1部分和第4部分为应用到CAS及由CAS到系统的过程,与CAS相关的仅仅是页面的跳转,其他的都是应用自身的逻辑;第3部分是使用CAS的客户端API处理CAS结果。
4.3.1.1 登录跳转
当应用系统处理到需要登录的请求,但当前会话为未登录状态时,需要提示用户进行登录。这在CAS单点登录系统中通常是要浏览器跳转到CAS主页完成的。对于Servlet方式来说,就是Filter + sendRedirect。其他框架可以用各自的方法,这里不做详述。
跳转的URL中,需要使用service参数提供在之前CAS客户端信息中提供的serviceId匹配的地址(参见4.1),在CAS端用户登录成功后,CAS会通过浏览器跳转到该地址,该地址需要能够处理Ticket验证请求。
URL举例(cas的应用上下文为cas):
http://cas.server.addr:8080/cas?service=http://application.server.addr:8080/login/cas
由于需要页面跳转,如果应用希望登录后回到刚才访问的页面(如典型的CAS已登录状态下自动完成登录的场景),应用需要在跳转前额外记录当前访问的地址以便登录完成后返回。
4.3.1.2 验证Ticket
用户于CAS登录成功后,CAS会通过浏览器跳转回应用serviceId指定的地址,并同时附带一个ticket参数提供给应用,应用端需要使用该ticket,在有效时间内(如10秒)向CAS服务器发请求进行ticket验证,验证成功后会返回CAS端登录的用户信息。
Ticket验证的过程处理可以是一个filter或是一个不需登录的servlet、action,验证请求的发送和返回可以通过调用CAS客户端API完成。处理方法如下例所示:
public Object validate(HttpServletRequest request) {
String ticket = request.getParameter("ticket");
if (ticket == null || ticket.isEmpty()) {
throw new RuntimeException("ticket not exists.");
}
String serviceId = "http://application.server.addr:8080/login/cas";
String casServerAddress = "http://cas.server.local.addr:8080/cas";
TicketValidator ticketValidator = new Cas20ServiceTicketValidator(casServerAddress);
Assertion assertion = null;
try {
assertion = ticketValidator.validate(ticket, serviceId);
} catch (TicketValidationException e) {
throw new RuntimeException("Ticket validation failed.", e);
}
return assertion.getPrincipal();
}
该示例方法会得到从CAS登录的用户(默认为登录名)。
4.3.1.3 完成登录
在应用中将从Ticket验证得到的用户ID按照应用的逻辑转化为登录用户,设置登录会话,完成登录并跳转到所需的登录后页面。这部分完全由应用代码完成。
4.3.2 登出
在有单点登录的情况下,登出操作分为应用本身的登出以及CAS端的登出。当进行需要单点登出(SLO)时,应用还需要能够接收在CAS端登出时的请求完成登出。
4.3.2.1 应用及CAS端登出
应用的登出操作需要在应用中通过应用自身的登录管理完成,由于采用了单点登录,在应用登出后还需要在CAS端执行登出,以完成应用真正的登出。具体实现上需要先在应用端会话做登出,然后跳转到CAS端的登出地址,完成CAS端登出。
CAS端登出地址形式如下:
http://cas.server.addr:8080/cas/logout?service=http://application.server.addr:8080/login/cas
4.3.2.2 后端SLO
在使用后端SLO的情况下,如果未在应用信息中提供logoutUrl(见4.1节),CAS服务端登出时会向所有已登录的服务,使用登录时提供的service参数中的地址发送登出请求。
一般情况下最简单的方法可以直接添加CAS Java客户端提供的Filter,自动处理CAS服务端的SLO请求完成登出。
例如,在web.xml中添加如下配置:
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value> http://cas.server.addr:8080/cas </param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
其中 casServerUrlPrefix
为CAS服务的地址。
该Filter会在登录验证Ticket时记录Ticket和HttpSession的关联,在登出请求处理时对对应的Session执行invalidate
。