SpringBoot集成CAS客户端实现单点登录功能
依赖的 jar 包:
<dependency>
<groupId>net.unicon.casgroupId>
<artifactId>cas-client-autoconfig-supportartifactId>
<version>1.5.0-GAversion>
dependency>
配置文件:
## CAS 配置
cas.validation-type = CAS
cas.server-url-prefix = http://192.168.80.96:8084/cas
cas.server-login-url = http://192.168.80.96:8084/cas/login
cas-server-logout-url = http://192.168.80.96:8084/cas/logout
cas.client-host-url = http://localhost:8080
开启 CAS Client 支持:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import net.unicon.cas.client.configuration.EnableCasClient;
@SpringBootApplication
@EnableCasClient // 启动CAS
public class SpringbootCasApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootCasApplication.class, args);
}
}
通过上面的配置就可以完成CAS的单点登录功能,CAS还有如下配置:
cas.authentication-url-patterns
cas.validation-url-patterns
cas.request-wrapper-url-patterns
cas.assertion-thread-local-url-patterns
cas.gateway
cas.use-session
cas.redirect-after-validation
cas.allowed-proxy-chains
cas.proxy-callback-url
cas.proxy-receptor-url
cas.accept-any-proxy
server.context-parameters.renew
依赖的 jar 包:
<dependency>
<groupId>org.jasig.cas.clientgroupId>
<artifactId>cas-client-coreartifactId>
<version>3.3.3version>
dependency>
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-webartifactId>
dependency>
配置文件:
## CAS 配置
spring.cas.sign-out-filters=/logout
spring.cas.auth-filters=/*
spring.cas.validate-filters=/*
spring.cas.request-wrapper-filters=/*
spring.cas.assertion-filters=/*
spring.cas.cas-server-login-url=http://192.168.80.96:8084/cas/login
spring.cas.cas-server-url-prefix=http://192.168.80.96:8084/cas
spring.cas.redirect-after-validation=true
spring.cas.use-session=true
spring.cas.server-name=http://localhost:8080
CAS的配置类:
属性值:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
// 获取配置文件中属性值
@Component
@ConfigurationProperties(prefix = "spring.cas")
public class SpringCasAutoConfig {
private static final String separator = ",";
private String validateFilters;
private String signOutFilters;
private String authFilters;
private String assertionFilters;
private String requestWrapperFilters;
private String casServerUrlPrefix;
private String casServerLoginUrl;
private String serverName;
private boolean useSession = true;
private boolean redirectAfterValidation = true;
public List getValidateFilters() {
return Arrays.asList(validateFilters.split(separator));
}
public void setValidateFilters(String validateFilters) {
this.validateFilters = validateFilters;
}
public List getSignOutFilters() {
return Arrays.asList(signOutFilters.split(separator));
}
public void setSignOutFilters(String signOutFilters) {
this.signOutFilters = signOutFilters;
}
public List getAuthFilters() {
return Arrays.asList(authFilters.split(separator));
}
public void setAuthFilters(String authFilters) {
this.authFilters = authFilters;
}
public List getAssertionFilters() {
return Arrays.asList(assertionFilters.split(separator));
}
public void setAssertionFilters(String assertionFilters) {
this.assertionFilters = assertionFilters;
}
public List getRequestWrapperFilters() {
return Arrays.asList(requestWrapperFilters.split(separator));
}
public void setRequestWrapperFilters(String requestWrapperFilters) {
this.requestWrapperFilters = requestWrapperFilters;
}
public String getCasServerUrlPrefix() {
return casServerUrlPrefix;
}
public void setCasServerUrlPrefix(String casServerUrlPrefix) {
this.casServerUrlPrefix = casServerUrlPrefix;
}
public String getCasServerLoginUrl() {
return casServerLoginUrl;
}
public void setCasServerLoginUrl(String casServerLoginUrl) {
this.casServerLoginUrl = casServerLoginUrl;
}
public String getServerName() {
return serverName;
}
public void setServerName(String serverName) {
this.serverName = serverName;
}
public boolean isRedirectAfterValidation() {
return redirectAfterValidation;
}
public void setRedirectAfterValidation(boolean redirectAfterValidation) {
this.redirectAfterValidation = redirectAfterValidation;
}
public boolean isUseSession() {
return useSession;
}
public void setUseSession(boolean useSession) {
this.useSession = useSession;
}
}
过滤器:
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.Cas20ProxyReceivingTicketValidationFilter;
import org.springframework.beans.factory.annotation.Autowired;
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.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
@Configuration
public class CasConfig {
// 是否启用CAS
private static boolean casEnabled = true;
@Autowired
private SpringCasAutoConfig autoConfig;
/**
* 用于实现单点登出功能
*/
@Bean
public ServletListenerRegistrationBean singleSignOutHttpSessionListener() {
ServletListenerRegistrationBean listener = new ServletListenerRegistrationBean<>();
listener.setEnabled(casEnabled);
listener.setListener(new SingleSignOutHttpSessionListener());
listener.setOrder(1);
return listener;
}
/**
* 该过滤器用于实现单点登出功能,单点退出配置,一定要放在其他filter之前
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean logOutFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
LogoutFilter logoutFilter = new LogoutFilter(autoConfig.getCasServerUrlPrefix() + "/logout?service=" + autoConfig.getServerName(), new SecurityContextLogoutHandler());
filterRegistration.setFilter(logoutFilter);
filterRegistration.setEnabled(casEnabled);
if (autoConfig.getSignOutFilters().size() > 0)
filterRegistration.setUrlPatterns(autoConfig.getSignOutFilters());
else
filterRegistration.addUrlPatterns("/logout");
filterRegistration.addInitParameter("casServerUrlPrefix", autoConfig.getCasServerUrlPrefix());
filterRegistration.addInitParameter("serverName", autoConfig.getServerName());
filterRegistration.setOrder(2);
return filterRegistration;
}
/**
* 该过滤器用于实现单点登出功能,单点退出配置,一定要放在其他filter之前
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean singleSignOutFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new SingleSignOutFilter());
filterRegistration.setEnabled(casEnabled);
if (autoConfig.getSignOutFilters().size() > 0)
filterRegistration.setUrlPatterns(autoConfig.getSignOutFilters());
else
filterRegistration.addUrlPatterns("/*");
filterRegistration.addInitParameter("casServerUrlPrefix", autoConfig.getCasServerUrlPrefix());
filterRegistration.addInitParameter("serverName", autoConfig.getServerName());
filterRegistration.setOrder(3);
return filterRegistration;
}
/**
* 该过滤器负责用户的认证工作
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean authenticationFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new AuthenticationFilter());
filterRegistration.setEnabled(casEnabled);
if (autoConfig.getAuthFilters().size() > 0)
filterRegistration.setUrlPatterns(autoConfig.getAuthFilters());
else
filterRegistration.addUrlPatterns("/*");
// casServerLoginUrl:cas服务的登陆url
filterRegistration.addInitParameter("casServerLoginUrl", autoConfig.getCasServerLoginUrl());
// 本项目登录ip+port
filterRegistration.addInitParameter("serverName", autoConfig.getServerName());
filterRegistration.addInitParameter("useSession", autoConfig.isUseSession() ? "true" : "false");
filterRegistration.addInitParameter("redirectAfterValidation", autoConfig.isRedirectAfterValidation() ? "true" : "false");
filterRegistration.setOrder(4);
return filterRegistration;
}
/**
* 该过滤器负责对Ticket的校验工作
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean cas20ProxyReceivingTicketValidationFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
Cas20ProxyReceivingTicketValidationFilter cas20ProxyReceivingTicketValidationFilter = new Cas20ProxyReceivingTicketValidationFilter();
cas20ProxyReceivingTicketValidationFilter.setServerName(autoConfig.getServerName());
filterRegistration.setFilter(cas20ProxyReceivingTicketValidationFilter);
filterRegistration.setEnabled(casEnabled);
if (autoConfig.getValidateFilters().size() > 0)
filterRegistration.setUrlPatterns(autoConfig.getValidateFilters());
else
filterRegistration.addUrlPatterns("/*");
filterRegistration.addInitParameter("casServerUrlPrefix", autoConfig.getCasServerUrlPrefix());
filterRegistration.addInitParameter("serverName", autoConfig.getServerName());
filterRegistration.setOrder(5);
return filterRegistration;
}
/**
* 该过滤器对HttpServletRequest请求包装,
* 可通过HttpServletRequest的getRemoteUser()方法获得登录用户的登录名
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean httpServletRequestWrapperFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new HttpServletRequestWrapperFilter());
filterRegistration.setEnabled(true);
if (autoConfig.getRequestWrapperFilters().size() > 0)
filterRegistration.setUrlPatterns(autoConfig.getRequestWrapperFilters());
else
filterRegistration.addUrlPatterns("/login");
filterRegistration.setOrder(6);
return filterRegistration;
}
/**
* 该过滤器使得可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。
* 比如AssertionHolder.getAssertion().getPrincipal().getName()。
* 这个类把Assertion信息放在ThreadLocal变量中,这样应用程序不在web层也能够获取到当前登录信息
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean assertionThreadLocalFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new AssertionThreadLocalFilter());
filterRegistration.setEnabled(true);
if (autoConfig.getAssertionFilters().size() > 0)
filterRegistration.setUrlPatterns(autoConfig.getAssertionFilters());
else
filterRegistration.addUrlPatterns("/*");
filterRegistration.setOrder(7);
return filterRegistration;
}
}
通过上面的配置,也可以完成CAS Client的认证