博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
cas5.3.2单点登录-编写自己的cas-starter(九)
阅读量:3786 次
发布时间:2019-05-22

本文共 11321 字,大约阅读时间需要 37 分钟。

原文地址,转载请注明出处:      © 

前言

写这篇文章的原因是在springBoot整合cas的过程中,我使用了一个别人写好的starter ,但是在整合单点登出的时候,发现多个客户端无法实现单点登出。经过查看源码,发现在这个starter中没有配置登出的filter。如果写成基于javaBean的配置也就一个类就能搞定,为了能学习一下如何实现一个 springboot的starter 所以来写一个 cas-client-spring-boot-starter。

使用SpringBoot可以快速开发基于Spring框架的项目,SpringBoot存在很多开箱即用的Starter依赖,使得我们在开发业务代码时能够非常方便的、不需要过多关注框架的配置,而只需要关注业务即可。只要按照springboot自动配置的模式来写,就可以实现自己的starter。

关于starter

使用一个公用starter的时候,只需要在Maven的配置文件中添加依赖即可,这个starter可能需要依赖很多jar包,在引用这个starter的同时,依赖的jar包也会自动导入,并且SpringBoot 在启动时会去依赖的starter包中寻找 resources/META-INF/spring.factories 文件,然后根据文件中配置的需要自动加载的类全路径,去加载该配置,并将Bean注入Spring Context 上下文当中。

我们也可以使用@ImportAutoConfiguration({CasAutoConfiguration.class}) 指定自动配置哪些类。
使用@SpringBootApplication(exclude = {CasAutoConfiguration.class}) 来取消自动配置。

实现过程

第一步:创建一个springboot项目,pom.xml完整依赖如下

4.0.0
priv.wangsaichao.cas
cas-client-spring-boot-starter
1.0.0
jar
cas-client-spring-boot-starter
SpringBoot cas client starter.
org.springframework.boot
spring-boot-starter-parent
2.0.0.RELEASE
org.springframework.boot
spring-boot-configuration-processor
true
org.springframework.boot
spring-boot-autoconfigure
org.jasig.cas.client
cas-client-core
3.5.0
javax.servlet
servlet-api
2.5
javax.validation
validation-api
1.1.0.Final
org.apache.maven.plugins
maven-compiler-plugin
3.5.1
1.8
1.8
maven-source-plugin
2.1
true
compile
jar

其中 spring-boot-configuration-processor 的作用是编译时生成 spring-configuration-metadata.json ,此文件主要给IDE使用。如当配置此jar相关配置属性在 application.properties ,你可以用ctlr+鼠标左键点击属性名,IDE会跳转到你配置此属性的类中。

关于artifactId中的名字cas-client-spring-boot-starter。Spring官方的Starter一般采取spring-boot-starter-{name} 的命名方式,如 spring-boot-starter-web 。
而非官方的Starter,官方建议 artifactId 命名应遵循{name}-spring-boot-starter 的格式。 例如:mybatis-spring-boot-starter

第二步:配置文件参数映射类

springboot提供了一个注解@ConfigurationProperties,该注解可以完成将application.properties配置文件内的有规则的配置参数映射到实体内的field内,不过需要提供setter方法,@ConfigurationProperties注解内我们使用到了属性preffix,该属性配置了读取参数的前缀,例如serverUrlPrefix属性,对应配置文件中内容就是 cas.server-url-prefix。完整类如下:

package priv.wangsaichao.cas.client.configuration;import org.springframework.boot.context.properties.ConfigurationProperties;import javax.validation.constraints.NotNull;/** * @author: WangSaiChao * @date: 2018/8/5 * @description: cas springboot 配置类 */@ConfigurationProperties(prefix = "cas", ignoreUnknownFields = false)public class CasClientConfigurationProperties {
/** * CAS server URL E.g. https://example.com/cas or https://cas.example. Required. * CAS 服务端 url 不能为空 */ @NotNull private String serverUrlPrefix; /** * CAS server login URL E.g. https://example.com/cas/login or https://cas.example/login. Required. * CAS 服务端登录地址 上面的连接 加上/login 该参数不能为空 */ @NotNull private String serverLoginUrl; /** * CAS-protected client application host URL E.g. https://myclient.example.com Required. * 当前客户端的地址 */ @NotNull private String clientHostUrl; /** * 忽略规则,访问那些地址 不需要登录 */ private String ignorePattern; /** * 自定义UrlPatternMatcherStrategy验证 */ private String ignoreUrlPatternType; public String getServerUrlPrefix() { return serverUrlPrefix; } public void setServerUrlPrefix(String serverUrlPrefix) { this.serverUrlPrefix = serverUrlPrefix; } public String getServerLoginUrl() { return serverLoginUrl; } public void setServerLoginUrl(String serverLoginUrl) { this.serverLoginUrl = serverLoginUrl; } public String getClientHostUrl() { return clientHostUrl; } public void setClientHostUrl(String clientHostUrl) { this.clientHostUrl = clientHostUrl; } public String getIgnorePattern() { return ignorePattern; } public void setIgnorePattern(String ignorePattern) { this.ignorePattern = ignorePattern; } public String getIgnoreUrlPatternType() { return ignoreUrlPatternType; } public void setIgnoreUrlPatternType(String ignoreUrlPatternType) { this.ignoreUrlPatternType = ignoreUrlPatternType; }}

第四步:编写AutoConfigure配置类

其实就是cas的那几个核心filter和监听,只不过是从web.xml中移到了基于javabean配置。

package priv.wangsaichao.cas.client.configuration;import org.jasig.cas.client.authentication.AuthenticationFilter;import org.jasig.cas.client.session.SingleSignOutFilter;import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;import org.jasig.cas.client.util.HttpServletRequestWrapperFilter;import org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.boot.web.servlet.FilterRegistrationBean;import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import java.util.EventListener;import java.util.HashMap;import java.util.Map;/** * @author: WangSaiChao * @date: 2018/8/6 * @description: 自动化配置类 */@Configuration@EnableConfigurationProperties(CasClientConfigurationProperties.class)public class CasClientConfiguration {
@Autowired CasClientConfigurationProperties configProps; /** * 配置登出过滤器 * @return */ @Bean public FilterRegistrationBean filterSingleRegistration() { final FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new SingleSignOutFilter()); // 设定匹配的路径 registration.addUrlPatterns("/*"); Map
initParameters = new HashMap
(); initParameters.put("casServerUrlPrefix", configProps.getServerUrlPrefix()); registration.setInitParameters(initParameters); // 设定加载的顺序 registration.setOrder(1); return registration; } /** * 配置过滤验证器 这里用的是Cas30ProxyReceivingTicketValidationFilter * @return */ @Bean public FilterRegistrationBean filterValidationRegistration() { final FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new Cas30ProxyReceivingTicketValidationFilter()); // 设定匹配的路径 registration.addUrlPatterns("/*"); Map
initParameters = new HashMap
(); initParameters.put("casServerUrlPrefix", configProps.getServerUrlPrefix()); initParameters.put("serverName", configProps.getClientHostUrl()); initParameters.put("useSession", "true"); registration.setInitParameters(initParameters); // 设定加载的顺序 registration.setOrder(2); return registration; } /** * 配置授权过滤器 * @return */ @Bean public FilterRegistrationBean filterAuthenticationRegistration() { final FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new AuthenticationFilter()); // 设定匹配的路径 registration.addUrlPatterns("/*"); Map
initParameters = new HashMap
(); initParameters.put("casServerLoginUrl", configProps.getServerLoginUrl()); initParameters.put("serverName", configProps.getClientHostUrl()); if(configProps.getIgnorePattern() != null && !"".equals(configProps.getIgnorePattern())){ initParameters.put("ignorePattern", configProps.getIgnorePattern()); } //自定义UrlPatternMatcherStrategy 验证规则 if(configProps.getIgnoreUrlPatternType() != null && !"".equals(configProps.getIgnoreUrlPatternType())){ initParameters.put("ignoreUrlPatternType", configProps.getIgnoreUrlPatternType()); } registration.setInitParameters(initParameters); // 设定加载的顺序 registration.setOrder(3); return registration; } /** * request wraper过滤器 * @return */ @Bean public FilterRegistrationBean filterWrapperRegistration() { final FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new HttpServletRequestWrapperFilter()); // 设定匹配的路径 registration.addUrlPatterns("/*"); // 设定加载的顺序 registration.setOrder(4); return registration; } /** * 添加监听器 * @return */ @Bean public ServletListenerRegistrationBean
singleSignOutListenerRegistration(){ ServletListenerRegistrationBean
registrationBean = new ServletListenerRegistrationBean
(); registrationBean.setListener(new SingleSignOutHttpSessionListener()); registrationBean.setOrder(1); return registrationBean; }}

第五步:编译基于注解启动方式

第一种方式:使用自定义spring.factories的方式自动配置,步骤如下:

src/main/resource目录下创建META-INF目录,并在目录内添加文件spring.factories,给@EnableAutoConfiguration去自动扫描,具体内容如下所示:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.wangsaichao.cas.client.configuration.CasClientConfiguration

基于spring.factories的方式配置,只需要在pom中添加依赖就可以了,项目启动,自动配置。

第二种:基于注解方式,代码如下:
package priv.wangsaichao.cas.client.configuration;import org.springframework.context.annotation.Import;import java.lang.annotation.*;/** * @author: WangSaiChao * @date: 2018/8/6 * @description: 配置该注解开启cas功能 */@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@Import(CasClientConfiguration.class)public @interface EnableCasClient {
}

使用时,在启动类上添加该注解,就可以了。目前为止我们的自定义starter已经配置完成,下面我们需要新建一个SpringBoot项目来测试我们的自动化配置是否已经生效。

测试

在之前依赖第三方starter的项目上进行改动

pom依赖修改为:
priv.wangsaichao.cas
cas-client-spring-boot-starter
1.0.0
application.properties添加以下属性
cas.server-url-prefix=https://server.cas.com:8443/cascas.server-login-url=https://server.cas.com:8443/cas/logincas.client-host-url=http://app2.cas.com:8082
在启动类上添加注解启动自动装配
package com.wangsaichao.cas;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import priv.wangsaichao.cas.client.configuration.EnableCasClient;/** * @author: WangSaiChao * @date: 2018/8/2 * @description: 启动类 */@SpringBootApplication@EnableCasClient//开启caspublic class Application {
public static void main(String[] args) { SpringApplication.run(Application.class, args); }}

启动两个项目测试(另一个是之前传统spring方式项目),结果如下:

这里写图片描述

你可能感兴趣的文章
Serial Communications in Win32
查看>>
STM32固件库详解
查看>>
IMediaEventEx 转帖
查看>>
Gamma校正
查看>>
Dll分配的内存块,应用释放的问题
查看>>
Python 设置系统默认编码(常见问题汇总)
查看>>
SQLZOO错题总结
查看>>
MySQL必知必会:单个表查询数据
查看>>
Java入门基础知识(一)构造函数,继承,重载与重写
查看>>
java应用——写一个超简单的QQ登录界面(没有监听)
查看>>
Java应用——高仿Windows XP画板(一)
查看>>
java应用——高仿XP画板(二:实现部分监听)
查看>>
java应用——高仿XP画板(三:加上重绘功能)
查看>>
java应用——高仿XP画板(四:整个代码)
查看>>
java入门基础知识(三)常用关键字
查看>>
java入门基础知识(四)(复习)内部类,流,继承
查看>>
java应用——斗地主(一:界面,洗牌发牌过程)
查看>>
java应用——斗地主(二:抢地主的过程)
查看>>
自学记录- 在Mac上学写python的hello world part one
查看>>
自学记录- 在Mac上学写python的hello world part two
查看>>