cas零散知识点

cas零散知识点



特别注意因为overlay模式下完成的,所以是拿新的类覆盖原有的类,如果新的不能覆盖原有的类就采用原有
的类,所有在resource下的一些配置文件你虽然没有配置但是依然会存在

关于模板

spring.thymeleaf.cache=false

这个配置没有在官网找到说明,是自己摸索出来的,服务端的HTML页面使用的是thymeleaf编写
(http://www.ultraq.net.nz/thymeleaf/layout)
thymeleaf默认会在启动的时候就把页面的静态内容给放到缓存里,这给我修改CAS默认登录页带来了很大的

麻烦,每次修改一点点页面内容,刷新是看不到效果的,只得重启服务,为了方便开发,

我把这个配置设成false,就是说不要缓存。

如果你也想修改登录页这里给出几个建议:

1、如果不懂thyeleaf先简单了解一下thymeleaf官网的demo写法;
2、登录页的模板是layout.html,其中有几个js是从谷歌CDN上下载的,而谷歌我们国内又访问不了,
这就会导致登录页加载非常慢,建议先把这几个js本地化;
3、登录页主要是casLoginView.html和fragments目录下的loginform.html;
4、layout.html引入了好几个类似logo.html,footer.html的页面,这几个页面看名字就知道干什么

的,建议对他们进行修改,改成自己的

*********************************************************************
*****************************分割线***********************************
*********************************************************************

关于返回多属性

#多属性
cas.authn.attributeRepository.jdbc[0].singleRow=true
cas.authn.attributeRepository.jdbc[0].order=0
cas.authn.attributeRepository.jdbc[0].url=jdbc:mysql://127.0.0.1:3306/CASTEST?
useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false
cas.authn.attributeRepository.jdbc[0].username=user_name
cas.authn.attributeRepository.jdbc[0].user=root
cas.authn.attributeRepository.jdbc[0].password=123456
cas.authn.attributeRepository.jdbc[0].sql=select * from cms_auth_user where {0}
cas.authn.attributeRepository.jdbc[0].dialect=org.hibernate.dialect.MySQLDialect
cas.authn.attributeRepository.jdbc[0].ddlAuto=none
cas.authn.attributeRepository.jdbc[0].driverClass=com.mysql.jdbc.Driver
cas.authn.attributeRepository.jdbc[0].leakThreshold=10
cas.authn.attributeRepository.jdbc[0].propagationBehaviorName=PROPAGATION_REQUIRED
cas.authn.attributeRepository.jdbc[0].batchSize=1
cas.authn.attributeRepository.jdbc[0].healthQuery=SELECT 1
cas.authn.attributeRepository.jdbc[0].failFast=true
CAS默认返回给客户端的只有用户ID,如果想返回更多的内容就要加上这段内容了,上面这个配置会返回cms_auth_user表下的所有字

段。

如何获取这些字段可以在客户端通过以下代码:

   AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal();
   final Map attributes = principal.getAttributes();

更详细的内容在客户端章节会给出

*********************************************************************
*****************************分割线***********************************
*********************************************************************
关于开启http
在配置文件application.properties中加入以下配置
# 开启 http 认证方式

cas.serviceRegistry.initFromJson=true

cas.tgc.secure=false

并修改以下配置,在其中加入http

笔记插图(第 2 页)

这些放在services目录的json文件来注册服务了,
先说一下这里的“服务”
其实指的就是客户端,更准确的说就是它的url,如果一个客户端没有注册到CAS的服务列表,
那么你通过客户端跳转到CAS,CAS会拒绝这个跳转。

war包解压出来的services里已经有了两个json文件,其中HTTPSandIMAPS-100xxxxxx.json中有一段:
"serviceId" : "^(https|imaps|http)://.*",
后边这部分是个正则表达式,为了支持http协议的客户端,我在里面加了个http,代表所有URL符合这个正则

表达式的服务都会被当成已经注册的服务

*********************************************************************
*****************************分割线***********************************
*********************************************************************

关于令牌

概念解读:

The TGT (Ticket Granting Ticket), stored in the TGC cookie, represents a SSO session for a user.

TGT保存在TGC(TGC是CAS服务端存放在浏览器端的cookie,主要就是用来保存TGT)中,服务端可以通过TGT来判断

是否有对应的用户SSO session(即用户在CAS服务端对应的session)存在。

The ST (Service Ticket), transmitted as a GET parameter in urls, stands for the access granted by the CAS server

to the CASified application for a specific user.

ST是CAS服务端为指定用户生成的用于访问某一个CAS客户端的字符串:浏览器和CAS服务端交互后,服务端生成

ST,并将浏览器重定向到CAS的客户端,此时重定向的地址中会包括ST,如此ST就被传递给了CAS的客户端,客户端

再拿着该ST去CAS服务端询问该ST是否有效。

*********************************************************************
*****************************分割线***********************************
*********************************************************************

关于配置文件获取

取配置文件处 CasJdbcAuthenticationConfiguration

笔记插图(第 3 页)

@ConditionalOnMissingBean(name = “jdbcAuthenticationHandlers”)

@Bean

@RefreshScope

public Collection<AuthenticationHandler> jdbcAuthenticationHandlers() {

final Collection<AuthenticationHandler> handlers = new HashSet<>();

final JdbcAuthenticationProperties jdbc = casProperties.getAuthn().getJdbc();

jdbc.getBind().forEach(b -> handlers.add(bindModeSearchDatabaseAuthenticationHandler(b)));

jdbc.getEncode().forEach(b -> handlers.add(queryAndEncodeDatabaseAuthenticationHandler(b)));

jdbc.getQuery().forEach(b -> handlers.add(queryDatabaseAuthenticationHandler(b)));

jdbc.getSearch().forEach(b -> handlers.add(searchModeSearchDatabaseAuthenticationHandler(b)));

return handlers;

}
*********************************************************************
*****************************分割线***********************************
*********************************************************************

关于自定义登陆部分

一、实现自定义处理部分

自定义验证很重要,因为我们后续的很多功能,都是基于自定义验证。

CAS服务器的org.apereo.cas.authentication.AuthenticationManager负责基于提供的凭证信息进行用户认证。与Spring

Security很相似,实际的认证委托给了一个或多个实现了org.apereo.cas.authentication.AuthenticationHandler接口的处

理类。在cas的认证过程中逐个执行authenticationHandlers中配置的认证管理,直到有一个成功为止。

CAS内置了一些AuthenticationHandler实现类,如下图所示,QueryDatabaseAuthenticationHandler中提供了基于jdbc

的用户认证。

如果需要实现自定义登录,只需要实现org.apereo.cas.authentication.AuthenticationHandler接口即可。当然也可以利用

已有的实现,比如创建一个继承自

org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler的类。

(org.apereo.cas.adaptors.jdbc.AbstractJdbcUsernamePasswordAuthenticationHandler这个是基于jdbc的认证继承这

个也可以的)

二、实现AuthenticationHandler之后还需要注册验证器

@Configuration(“myAuthenticationConfiguration”)

@EnableConfigurationProperties(CasConfigurationProperties.class)

public class MyAuthenticationConfiguration implements AuthenticationEventExecutionPlanConfigurer {

@Autowired

    private CasConfigurationProperties casProperties;

@Autowired

@Qualifier(“servicesManager”)

    private ServicesManager servicesManager;

/**

* 将自定义验证器注册为Bean

* @return

*/

@Bean

    public AuthenticationHandler myAuthenticationHandler() {

MyAuthenticationHandler handler = new

MyAuthenticationHandler(MyAuthenticationHandler.class.getSimpleName(), servicesManager, new

DefaultPrincipalFactory(), 1);

return handler;

    }

/**

* 注册验证器

* @param plan

*/

@Override

    public void configureAuthenticationExecutionPlan(AuthenticationEventExecutionPlan plan) {

plan.registerAuthenticationHandler(myAuthenticationHandler());

    }
}

三、最后需要把这个注册器加载进去

加载该配置类

在resources\META-INF\spring.factories中配置该类

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.wangsaichao.cas.config.MyAuthenticationCon

figuration

*********************************************************************
*****************************分割线***********************************
*********************************************************************
restful请求

写完接口后在spring.factors的配置文件上加入这个com.dym.controller.CasRestPdController就可以达到我们自

己的restful

笔记插图(第 5 页)

笔记插图(第 5 页)

*********************************************************************
*****************************分割线***********************************
*********************************************************************
注册service
cas中存在一个叫service的东西,这个service和我们平常说的不是一个东西,这个service是指cas客户
端接入。只有经过cas允许的客户端才能使用cas,也就相当于我们的客户端要使用cas的前提是必须要先在
cas里面注册自己的信息。这个信息就是所谓的service。
cas里面有好多方式存储这个service,比如下面的这些:
1、JSON(通过json文件存储)
2、LDAP
3、InMemory 通过bean在内存存储
4、JPA数据库存储
5、yml文件存储
6、mogodb存储
我们开始默认使用的是json,可能眼尖的人会发现我们放在tomcat里面运行的时候,在文件夹web-inf的
classes文件夹下有个services的文件夹。也就是下图的这样

命名方式

笔记插图(第 6 页)

看这个结构我们可以发现第一行的@class这个是通用的,所有的这种都是用这个来的,代表注册服务的意思。

第二行的serviceId代表的是我们注册的客户端的地址,这里可以使用正则匹配,这个可是重中之重,因为你
的客户端能不能使用其实就是靠这种文件里面的这个字段是不是能匹配上你的客户端的url,我们这边匹配的是
以https或者imaps开头的所有地址。如果你的cas客户端的地址是以http开头的,而你没有去改这个配置文
件,那么很不好意思,你去进行单点登录的时候,cas会提示你这个是未认证的服务。

还有个第三行的name代表的是其实就是一个名称而已,之后会显示在你的登录页面上,如果你不重新改cas的

页面的话。这个也是必须填写的。

第四行的id,这个应该不用我说吧,这个其实代表的唯一性,相当于我们的主键,(可以这么理解)。

第5行表示的是描述,这个见名之意,其实就是描述你这个文件主要是用来做什么的,主要用于之后维护的时候

告诉你这个文件的作用,因为一旦文件多的时候,有注释会让你更方便的找到一些东西。

第6行的evaluationOrder其实代表的就是执行的顺序ps(也不算吧),只能想当与spring中的@order的

注解吧。

这个是基本的一个service的文件,其实里面有更多的东西,比如返回的属性、登出的方式以及登出的地址,
等等。甚至还有关于oauth2等的配置信息,其实都可以写在这个配置文件中,还有一个比较重要的属性就是返

回数据属性的设置

“`
“attributeReleasePolicy” : {
“@class” : “org.apereo.cas.services.ReturnAllAttributeReleasePolicy”
}

这个其实有好几种返回属性的方式,我这边使用的是返回所有的,就是相当于你自己在登录成功后塞进map里面
的属性都能使用这个让cas客户端接收到,记住cas客户端要使用cas3进行接收啊。
好了大致的service的配置我们也讲了,但是我们如何去读取他呢,这时候cas提供的一种读取的方式就上场

了

在cas的properties配置文件中首先要打开这个配置

cas.serviceRegistry.initFromJson=true//这个代表的是运行读取json配置文件
cas.serviceRegistry.watcherEnabled=true//这个代表的是自动扫描,默认是开启的
cas.serviceRegistry.repeatInterval=120000//代表的是多久扫描一次
cas.serviceRegistry.startDelay=15000//延迟15秒开启
cas.serviceRegistry.config.location=classpath:/services
//这个代表的是我们放置的services的路径

配置好上面的这些,我们的cas就能开始运行了。因为他能扫描到我们注册的服务,即使你在某个时刻更改了,
虽然不是马上生效,但是两分钟后他就能生效,因为他在两分钟后就会进行重新扫描这些json文件

注册service的类是org.apereo.cas.services.AbstractServicesManager

在包cas-server-core-services-registry下

其中通过它ServiceRegistryDao加载service,实现类有JsonServiceRegistryDao、

InMemoryServiceRegistry等

检车service是否合法在类ServiceAuthorizationCheck.doExecute()里面实现

最终的比对是在AbstractServicesManager.findServiceBy(final String serviceId)里进行正则匹

配的。

以上在包cas-server-support-actions下

数据库动态操作service也是操作 servicesManager

@Autowired

@Qualifier(“servicesManager”)

private ServicesManager servicesManager;
*********************************************************************
*****************************分割线***********************************
*********************************************************************
关于ticket的管理

顶级接口TicketRegistry

AbstractTicketRegistry implements TicketRegistry

默认是由DefaultTicketRegistry 来管理

由一个map存放

笔记插图(第 8 页)

笔记插图(第 8 页)

*********************************************************************
*****************************分割线***********************************
*********************************************************************退出调用 流程

ActionExecutor.execute->AnnotatedAction.execute->AbstractAction.execute-

>TerminateSessionAction.doExecute->DefaultLogoutManager.performLogout-

>DefaultSingleLogoutServiceMessageHandler.handle-

>DefaultSingleLogoutServiceMessageHandler.performBackChannelLogout发送http post请

求

*********************************************************************
*****************************分割线***********************************
*********************************************************************
ticket校验流程

CentralAuthenticationService的实现为DefaultCentralAuthenticationService,该实现在cas-server-core模块里面,作用

为TGT、ST的生成、存储、检测

作者:只把他乡作故乡

链接:https://www.jianshu.com/p/ddf86242c00d

来源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

*********************************************************************
*****************************分割线***********************************
*********************************************************************

session的保存和销毁。大家可以直接找到SingleSignOutHandler这个类

recordSession和destroySession的方法

进入之后可以清楚的看到我们客户端生成session的时候会将token和session保存到

sessionMappingStorage.addSessionById(token, session);这里面,而这其中的token其实就是St,

在生成session的同时,会将session和st票据存到map中,sessionid和st也存到map中,这个时候我们就

可以在这里增加redis储存st和sessionid的操作。

*********************************************************************
*****************************分割线***********************************
*********************************************************************
重写cas内部方法,文档提示如下图

Overrides

What if you needed to override the definition of a CAS-provided bean and replace it entirely with

your own?

This is where components come to aid. Most component/bean definitions in CAS are registered

with some form of tag that indicates to the bootstrapping process to ignore their creation, if a

bean definition with the same id is already defined. This means you can create your own

configuration class, register it and the design a definition only to have the context utilize yours

rather than what ships with CAS by default.@Conditional@Conditional@Bean

笔记插图(第 10 页)

笔记插图(第 10 页)

@Conditional

springboot中@Conditional注解的作用,在我们常用的声明一个配置类时,我们都会采用注解的方法,

@Configuration和@Bean一起搭配使用,@Configuration是指明当前类是一个配置类,就是代替之前的

spring配置文件,在配置文件中用<bean><bean/>标签添加组件,但是现在有注解

* @Bean:就是将方法的返回值添加到容器中,容器中的这个组件默认的id就是方法名

当我们再了解springboot自动装配的源码中,我们会发现有很多的组件,springboot在启动时会去加载,

会发现在META-INF下会有spring.factories的配置,而且在配置时会从properties类中获取属性,我们可

以在配置文件中指定这些属性的值。但是在用@Configuration注解时,我们可以指定满足什么条件才会

向容器中添加组件。就是我们下面要扩展的。Condition是一个接口,接口中有一个matches方法,返回

值类型是boolean类型.今天我们只说@Conditional的使用,其他的都是一样的。

笔记插图(第 11 页)

*********************************************************************
*****************************分割线***********************************
*********************************************************************

ProxyTicketProperties

numberOfUses 使用的次数

ticket 10s失效

笔记插图(第 11 页)

笔记插图(第 12 页)