CAS单点登录:集成客户端,自定义client-starter(二)
0.说明
本系列文章只根据自己的需要做部分定制,完整的教程见:https://blog.csdn.net/qq_34021712/category_9278675.html
有兴趣的可以一起研究。
1.服务端
1.1.Service配置
客户端接入 CAS 首先需要在服务端进行注册,否则客户端访问将提示“未认证授权的服务”警告:

简单需求:对所有https和http请求的service进行允许认证。
在resources/services下新建文件fdzang-1000.json,这个文件是我根据cas源代码HTTPSandIMAPS-10000001.json更改的。路径:cas\WEB-INF\classes\services
{
"@class": "org.apereo.cas.services.RegexRegisteredService",
"serviceId": "^(https|imaps|http)://.*",
"name": "fdzang",
"id": 1000,
"description": "CAS-SSO 登入",
"evaluationOrder": 10000
}
注意:
services目录中可包含多个 JSON 文件,其命名必须:${name}-${id}.json,id必须为json文件中内容id一致
对其中属性的说明如下,更多详细内容见:官方文档-Service-Management。
- @class:必须为org.apereo.cas.services.RegisteredService的实现类
- serviceId:对服务进行描述的表达式,可用于匹配一个或多个 URL 地址
- name: 服务名称
- id:全局唯一标志
- description:服务描述,会显示在默认登录页
- evaluationOrder:定义多个服务的执行顺序
1.2.修改application.properties
配置好service之后,根据官方文档-service-registry,还需修改 application.properties 文件告知 CAS 服务端从本地加载服务定义文件
# 注册客户端 cas.serviceRegistry.initFromJson=true
2.自定义client-starter
2.1.创建项目
创建一个springboot项目,pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.fdzang</groupId>
<artifactId>cas-client-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 引用依赖的父包 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- 配置该插件将源码放入仓库 -->
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.1</version>
<configuration>
<attach>true</attach>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
2.2.加载配置文件
这个类主要的作用是读取client端application.yml中,关于cas相关的配置
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import javax.validation.constraints.NotNull;
@Data
@ConfigurationProperties(prefix = "cas", ignoreUnknownFields = false)
public class CasClientConfigurationProperties {
/**
* CAS 服务端 url 不能为空
*/
@NotNull
private String serverUrlPrefix;
/**
* CAS 服务端登录地址 上面的连接 加上/login 该参数不能为空
*/
@NotNull
private String serverLoginUrl;
/**
* 当前客户端的地址
*/
@NotNull
private String serverName;
/**
* 忽略规则,访问那些地址 不需要登录
*/
private String ignorePattern;
/**
* 认证的URL
*/
private String authrizationUrl;
}
2.3.编写AutoConfigure配置类
这些自动注入的配置,能够让客户端实现接入cas。
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.AssertionThreadLocalFilter;
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 org.springframework.util.StringUtils;
import java.util.EventListener;
import java.util.HashMap;
import java.util.Map;
@Configuration
@EnableConfigurationProperties(CasClientConfigurationProperties.class)
public class CasClientConfiguration {
@Autowired
CasClientConfigurationProperties configProps;
@Bean
public FilterRegistrationBean filterSingleRegistration() {
final FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new SingleSignOutFilter());
registration.addUrlPatterns("/*");
registration.setOrder(1);
Map<String, String> params = new HashMap<String, String>();
params.put("casServerUrlPrefix", configProps.getServerUrlPrefix());
params.put("serverName", configProps.getServerName());
registration.setInitParameters(params);
return registration;
}
@Bean
public ServletListenerRegistrationBean<EventListener> singleSignOutListenerRegistration() {
ServletListenerRegistrationBean<EventListener> registrationBean = new ServletListenerRegistrationBean<EventListener>();
registrationBean.setListener(new SingleSignOutHttpSessionListener());
registrationBean.setOrder(1);
return registrationBean;
}
@Bean
public FilterRegistrationBean filterAuthenticationRegistration() {
final FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new AuthenticationFilter());
registration.addUrlPatterns("/*");
registration.setOrder(2);
Map<String, String> params = new HashMap<String, String>();
params.put("casServerLoginUrl", configProps.getServerLoginUrl());
params.put("serverName", configProps.getServerName());
if (!StringUtils.isEmpty(configProps.getIgnorePattern())) {
params.put("ignorePattern", configProps.getIgnorePattern());
}
registration.setInitParameters(params);
return registration;
}
@Bean
public FilterRegistrationBean filterValidationRegistration() {
final FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new Cas30ProxyReceivingTicketValidationFilter());
registration.addUrlPatterns("/*");
registration.setOrder(3);
Map<String, String> params = new HashMap<String, String>();
params.put("casServerUrlPrefix", configProps.getServerUrlPrefix());
params.put("serverName", configProps.getServerName());
params.put("useSession", "true");
registration.setInitParameters(params);
return registration;
}
@Bean
public FilterRegistrationBean filterWrapperRegistration() {
final FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new HttpServletRequestWrapperFilter());
registration.addUrlPatterns("/*");
registration.setOrder(4);
return registration;
}
@Bean
public FilterRegistrationBean casAssertionThreadLocalFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new AssertionThreadLocalFilter());
registration.addUrlPatterns("/*");
registration.setOrder(5);
return registration;
}
}
2.4.编译基于注解启动方式
客户端只需要在启动类上加上@EnableCasClient注解即可实现接入cas
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(CasClientConfiguration.class)
public @interface EnableCasClient {
}
3.客户端
3.1.新建项目
新建一个springboot项目,pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.fdzang</groupId>
<artifactId>cas-client</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.9.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.cas.client.version>3.5.0</java.cas.client.version>
</properties>
<dependencies>
<dependency>
<groupId>com.fdzang</groupId>
<artifactId>cas-client-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
3.2.配置文件application.yml
server: port: 8082 cas: server-url-prefix: https://server.cas.com:8443/cas server-login-url: https://server.cas.com:8443/cas/login server-name: http://127.0.0.1:8082
3.3.主启动类
import com.fdzang.cas.client.configuration.EnableCasClient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableCasClient
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
3.4.测试接口
import com.fdzang.cas.client.configuration.CasClientConfigurationProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@RestController
public class UserController {
@Autowired
CasClientConfigurationProperties configProps;
@GetMapping("/login")
public String login(HttpServletRequest request, HttpServletResponse response) throws IOException {
String username = request.getRemoteUser();
return username;
}
@GetMapping("/logout")
public void loginOut(HttpServletRequest request, HttpServletResponse response) throws IOException {
String url = configProps.getServerUrlPrefix() + "/logout?service=" + configProps.getServerName();
response.sendRedirect(url);
}
}


浙公网安备 33010602011771号