CAS-5.3单点登录/退出客户端搭建(Springboot)
2018-09-17 本文已影响0人
那些流逝的岁月
使用Springboot搭建cas客户端,主要是配置四个过滤器和一个监听器。
单点登录
创建过滤器类
用于过滤不需要登录的用户,需要实现UrlPatternMatcherStrategy 接口,在matches 函数里添加不需要用户登录的链接。
package com.zhang.springbootcasclient1.auth;
import org.jasig.cas.client.authentication.UrlPatternMatcherStrategy;
import java.util.regex.Pattern;
/**
* @Auther: zhang
* @Date: 2018/8/30 09:46
* @Description:过滤掉不需要授权登录的页面
*/
public class SimpleUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy{
private Pattern pattern;
/**
* description:判断是否匹配这个字符串
* @param: [url]用户请求的连接
* @return: true:不需要拦截
* false:必须要登录
*/
@Override
public boolean matches(String url) {
//使用正则表达式来匹配需要忽略的连接
return this.pattern.matcher(url).find();
}
/**
* description:正则表达式的规则,该规则在配置AuthenticationFilter的ignorePattern中设置
* @param: [pattern]
* @return: void
*/
@Override
public void setPattern(String pattern) {
this.pattern = Pattern.compile(pattern);
}
}
创建首页控制器
package com.zhang.springbootcasclient1.controller;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.validation.Assertion;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
import java.util.Map;
/**
* @Auther: zhangll
* @Date: 2018/8/30 10:11
* @Description:
*/
@Controller
public class IndexController {
@RequestMapping(value={"/", "/index"})
public String index(HttpServletRequest request) {
//获取cas给我们传递回来的对象,这个对象在Session中
//session的 key是 CONST_CAS_ASSERTION
Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
Principal principal = assertion.getPrincipal();
String loginName =principal.getName();
System.out.printf("登录用户名:%s\r\n",loginName);
System.out.printf("ValidFromDate:%s\r\n",assertion.getValidFromDate());
System.out.printf("ValidUntilDate:%s\r\n",assertion.getValidUntilDate());
System.out.printf("AuthenticationDate:%s\r\n",assertion.getAuthenticationDate());
//获取自定义返回值的数据
if (principal instanceof AttributePrincipal) {
//cas传递过来的数据
Map<String,Object> result =( (AttributePrincipal)principal).getAttributes();
for(Map.Entry<String, Object> entry :result.entrySet()) {
String key = entry.getKey();
Object val = entry.getValue();
System.out.printf("%s:%s\r\n",key,val);
}
}
return "index";
}
}
首页代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>当前所在子系统:测试系统1</h1>
<h2><a href="http://springbootcasclient.com:8001/">系统1</a></h2>
<h2><a href="http://springbootcasclient.com:8002/">系统2</a></h2>
<b>Authenticated User Id:</b> <a href="logout.jsp" title="Click here to log out" th:text="${#request.remoteUser}"/>
<br/>
<a th:href="${#request.contextPath}+'/logoutDefault'" title="Click here to log out">退出系统(默认退出页面)</a>
<a th:href="${#request.contextPath}+'/logoutCustom'" title="Click here to log out">退出系统(定制退出页面)</a>
</body>
</html>
用户退出控制器
package com.zhang.springbootcasclient1.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
/**
* @Auther: zhangll
* @Date: 2018/8/30 11:35
* @Description:
*/
@Controller
public class LogoutController {
@RequestMapping("/logoutDefault")
public String logout1(HttpSession session) {
session.invalidate();
// 直接退出,走默认退出方式
return "redirect:https://casserver.com:8443/logout";
}
@RequestMapping("/logoutCustom")
public String logout2(HttpSession session) {
session.invalidate();
// 退出登录后,跳转到退出成功的页面,不走默认页面
return "redirect:https://casserver.com:8443/logout?service=http://springbootcasclient.com:8001/logout/success";
}
@RequestMapping("/logout/success")
@ResponseBody
public String logout2() {
return "系统1注销成功";
}
}
配置过滤器到springboot
package com.zhang.springbootcasclient1;
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.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import java.util.EventListener;
import java.util.HashMap;
import java.util.Map;
@SpringBootApplication
public class SpringbootCasClient1Application {
private static final String CAS_SERVER_URL_PREFIX = "https://casserver.com:8443/";
private static final String CAS_SERVER_URL_LOGIN = "https://casserver.com:8443/login";
//本机的名称
private static final String SERVER_NAME = "http://springbootcasclient.com:8001/";
/**
* description: 登录过滤器
* @param: []
* @return: org.springframework.boot.web.servlet.FilterRegistrationBean
*/
@Bean
public FilterRegistrationBean filterSingleRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new SingleSignOutFilter());
// 设定匹配的路径
registration.addUrlPatterns("/*");
Map<String,String> initParameters = new HashMap<String, String>();
initParameters.put("casServerUrlPrefix", CAS_SERVER_URL_PREFIX);
registration.setInitParameters(initParameters);
// 设定加载的顺序
registration.setOrder(1);
return registration;
}
/**
* description:过滤验证器
* * @param: []
* @return: org.springframework.boot.web.servlet.FilterRegistrationBean
*/
@Bean
public FilterRegistrationBean filterValidationRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new Cas30ProxyReceivingTicketValidationFilter());
// 设定匹配的路径
registration.addUrlPatterns("/*");
Map<String,String> initParameters = new HashMap<String, String>();
initParameters.put("casServerUrlPrefix", CAS_SERVER_URL_PREFIX);
initParameters.put("serverName", SERVER_NAME);
initParameters.put("useSession", "true");
registration.setInitParameters(initParameters);
// 设定加载的顺序
registration.setOrder(1);
return registration;
}
/**
* description:授权过滤器
* @param: []
* @return: org.springframework.boot.web.servlet.FilterRegistrationBean
*/
@Bean
public FilterRegistrationBean filterAuthenticationRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new AuthenticationFilter());
// 设定匹配的路径
registration.addUrlPatterns("/*");
Map<String,String> initParameters = new HashMap<String, String>();
initParameters.put("casServerLoginUrl", CAS_SERVER_URL_LOGIN);
initParameters.put("serverName", SERVER_NAME);
//忽略/logout的路径
initParameters.put("ignorePattern", "/logout/*");
initParameters.put("ignoreUrlPatternType", "com.zhang.springbootcasclient1.auth.SimpleUrlPatternMatcherStrategy");
registration.setInitParameters(initParameters);
// 设定加载的顺序
registration.setOrder(1);
return registration;
}
/**
* wraper过滤器
* @return
*/
@Bean
public FilterRegistrationBean filterWrapperRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new HttpServletRequestWrapperFilter());
// 设定匹配的路径
registration.addUrlPatterns("/*");
// 设定加载的顺序
registration.setOrder(1);
return registration;
}
/**
* 添加监听器
* @return
*/
@Bean
public ServletListenerRegistrationBean<EventListener> singleSignOutListenerRegistration(){
ServletListenerRegistrationBean<EventListener> registrationBean = new ServletListenerRegistrationBean<EventListener>();
registrationBean.setListener(new SingleSignOutHttpSessionListener());
registrationBean.setOrder(1);
return registrationBean;
}
public static void main(String[] args) {
SpringApplication.run(SpringbootCasClient1Application.class, args);
}
}
application.properties
logging.file=logs/config/springboot-cas-client1.log
info.name=springboot-cas-client1
server.port=8001
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.zhang</groupId>
<artifactId>springboot-cas-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-cas-client</name>
<description>Demo project for Spring Boot CAS Client</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<java.cas.client.version>3.5.0</java.cas.client.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--cas客户端 -->
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>${java.cas.client.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
登录测试
按照同样的方法实现客户端系统2。
启动cas服务器端和两个客户端。输入http://springbootcasclient.com:8001/,则跳转到登录界面
输入用户名和密码(casuser/Mellon),则进入客户端系统1的index页面。
client1-index.png
输入http://springbootcasclient.com:8002/,直接跳转到客户端系统2的index页面,不需要再重新登录。
client2-index.png
单点退出
单点退出,需要下面三个步骤:1、添加过滤器类,过滤掉不需要登录的url;2、添加退出跳转的控制器;3、修改服务端application.properties ,加cas.logout.followServiceRedirects=true,让客户端可以自己制定退出的路径,否则会走默认退出路径。
添加过滤器类
过滤器类需要实现UrlPatternMatcherStrategy接口,然后配置到springboot中,请参考单点登录的创建过滤器类和配置过滤器到springboot。
添加退出控制器
退出的方式有两种,一种是走默认的路径,另一种是走自定义的返回路径。请参考单点登录的用户退出控制器。
修改服务端application.properties
cas.logout.followServiceRedirects=true
将上面的内容添加到applicaiton.properties, 这样就可以允许客户端定制自己的退出路径了。
注意问题
http协议配置:cas 5.3.x默认客户端不支持http协议, 如果不进行配置,则会出现“未认证授权的服务”错误。
unauthorized-service-error.png
要配置兼容http协议,需要在HTTPSandIMAPS-10000001.json文件中添加http。
HTTPSandIMAPS-10000001.png
同时需要在application.properties中添加
cas.serviceRegistry.initFromJson=true