Springboot之整合cas client
CAS client在github的示例项目使用的是web.xml来配置过滤器
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<!--
<context-param>
<param-name>renew</param-name>
<param-value>true</param-value>
</context-param>
-->
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>https://mmoayyed.unicon.net:8443/cas</param-value>
</init-param>
</filter>
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<filter>
<filter-name>CAS Authentication Filter</filter-name>
<!--<filter-class>org.jasig.cas.client.authentication.Saml11AuthenticationFilter</filter-class>-->
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>https://mmoayyed.unicon.net:8443/cas/login</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>https://mmoayyed.unicon.net:9443</param-value>
</init-param>
</filter>
<filter>
<filter-name>CAS Validation Filter</filter-name>
<!--<filter-class>org.jasig.cas.client.validation.Saml11TicketValidationFilter</filter-class>-->
<filter-class>org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>https://mmoayyed.unicon.net:8443/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>https://mmoayyed.unicon.net:9443</param-value>
</init-param>
<init-param>
<param-name>redirectAfterValidation</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>useSession</param-name>
<param-value>true</param-value>
</init-param>
<!--
<init-param>
<param-name>acceptAnyProxy</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>proxyReceptorUrl</param-name>
<param-value>/sample/proxyUrl</param-value>
</init-param>
<init-param>
<param-name>proxyCallbackUrl</param-name>
<param-value>https://mmoayyed.unicon.net:9443/sample/proxyUrl</param-value>
</init-param>
-->
<init-param>
<param-name>authn_method</param-name>
<param-value>mfa-duo</param-value>
</init-param>
</filter>
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Authentication Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>
index.jsp
</welcome-file>
</welcome-file-list>
</web-app>
但是Springboot项目当中不使用xml文件配置,使用Java config配置注解,这也不是什么难事,配置如下:
import java.util.EventListener;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Filter;
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.Cas20ProxyReceivingTicketValidationFilter;
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;
/**
* @author Barry
* @date 2018年9月20日 下午2:10:47
*/
@Configuration
public class CasFilterConfig {
private static final String CAS_SERVER_URL_PREFIX = "http://localhost:8900/cas";
private static final String SERVER_NAME = "http://localhost:9988";
/**
* SingleSignOutFilter
* 必须放在最前面
*/
@Bean
public FilterRegistrationBean<SingleSignOutFilter> filterSingleRegistration() {
FilterRegistrationBean<SingleSignOutFilter> registration = new FilterRegistrationBean<SingleSignOutFilter>();
registration.setFilter(new SingleSignOutFilter());
Map<String,String> initParameters = new HashMap<String,String>();
initParameters.put("casServerUrlPrefix",CAS_SERVER_URL_PREFIX );
registration.setInitParameters(initParameters);
//set mapping url
registration.addUrlPatterns("/*");
//set loading sequence
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;
}
/**
* 授权过滤器
* @return
*/
@Bean
public FilterRegistrationBean<AuthenticationFilter> filterAuthenticationRegistration() {
FilterRegistrationBean<AuthenticationFilter> registration = new FilterRegistrationBean<AuthenticationFilter>();
registration.setFilter(new AuthenticationFilter());
// 设定匹配的路径
registration.addUrlPatterns("/*");
Map<String,String> initParameters = new HashMap<String, String>();
initParameters.put("casServerLoginUrl", CAS_SERVER_URL_PREFIX);
initParameters.put("serverName", SERVER_NAME);
registration.setInitParameters(initParameters);
//设定加载的顺序
registration.setOrder(1);
return registration;
}
/**
* CAS Validation Filter
* @return
*/
@Bean
public FilterRegistrationBean<Filter> filterValidationRegistration() {
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
registration.setFilter(new Cas20ProxyReceivingTicketValidationFilter());
//set mapping url
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;
}
/**
* wraper过滤器
* @return
*/
@Bean
public FilterRegistrationBean<HttpServletRequestWrapperFilter> filterWrapperRegistration() {
FilterRegistrationBean<HttpServletRequestWrapperFilter> registration = new FilterRegistrationBean<HttpServletRequestWrapperFilter>();
registration.setFilter(new HttpServletRequestWrapperFilter());
// 设定匹配的路径
registration.addUrlPatterns("/*");
// 设定加载的顺序
registration.setOrder(1);
return registration;
}
}
这样就可以拦截请求,转到cas server登录和退出。
但是Springboot是个爸爸呀,默认大于配置,因此很多东西都有默认的配置,这种事怎么可能没做呢!原来启用注解@EnableCasClient即可。但是需要在pom文件中引入包
<dependency>
<groupId>net.unicon.cas</groupId>
<artifactId>cas-client-autoconfig-support</artifactId>
<version>1.7.0-GA</version>
</dependency>
查看源码
@Bean
public FilterRegistrationBean casAuthenticationFilter() {
final FilterRegistrationBean authnFilter = new FilterRegistrationBean();
final Filter targetCasAuthnFilter =
(this.configProps.getValidationType() == CAS || configProps.getValidationType() == CAS3) ? new AuthenticationFilter()
: new Saml11AuthenticationFilter();
initFilter(authnFilter,
targetCasAuthnFilter,
2,
constructInitParams("casServerLoginUrl", this.configProps.getServerLoginUrl(), this.configProps.getClientHostUrl()),
this.configProps.getAuthenticationUrlPatterns());
if (this.configProps.getGateway() != null) {
authnFilter.getInitParameters().put("gateway", String.valueOf(this.configProps.getGateway()));
}
if (this.casClientConfigurer != null) {
this.casClientConfigurer.configureAuthenticationFilter(authnFilter);
}
return authnFilter;
}
@Bean
public FilterRegistrationBean casHttpServletRequestWrapperFilter() {
final FilterRegistrationBean reqWrapperFilter = new FilterRegistrationBean();
reqWrapperFilter.setFilter(new HttpServletRequestWrapperFilter());
if (this.configProps.getRequestWrapperUrlPatterns().size() > 0) {
reqWrapperFilter.setUrlPatterns(this.configProps.getRequestWrapperUrlPatterns());
}
reqWrapperFilter.setOrder(3);
if (this.casClientConfigurer != null) {
this.casClientConfigurer.configureHttpServletRequestWrapperFilter(reqWrapperFilter);
}
return reqWrapperFilter;
}
@Bean
public FilterRegistrationBean casAssertionThreadLocalFilter() {
final FilterRegistrationBean assertionTLFilter = new FilterRegistrationBean();
assertionTLFilter.setFilter(new AssertionThreadLocalFilter());
if (this.configProps.getAssertionThreadLocalUrlPatterns().size() > 0) {
assertionTLFilter.setUrlPatterns(this.configProps.getAssertionThreadLocalUrlPatterns());
}
assertionTLFilter.setOrder(4);
if (this.casClientConfigurer != null) {
this.casClientConfigurer.configureAssertionThreadLocalFilter(assertionTLFilter);
}
return assertionTLFilter;
}
@Autowired(required = false)
void setConfigurers(Collection<CasClientConfigurer> configurers) {
if (CollectionUtils.isEmpty(configurers)) {
return;
}
if (configurers.size() > 1) {
throw new IllegalStateException(configurers.size() + " implementations of " +
"CasClientConfigurer were found when only 1 was expected. " +
"Refactor the configuration such that CasClientConfigurer is " +
"implemented only once or not at all.");
}
this.casClientConfigurer = configurers.iterator().next();
}
private Map<String, String> constructInitParams(final String casUrlParamName, final String casUrlParamVal, final String clientHostUrlVal) {
final Map<String, String> initParams = new HashMap<>(2);
initParams.put(casUrlParamName, casUrlParamVal);
initParams.put("serverName", clientHostUrlVal);
return initParams;
}
private void initFilter(final FilterRegistrationBean filterRegistrationBean,
final Filter targetFilter,
int filterOrder,
final Map<String, String> initParams,
List<String> urlPatterns) {
filterRegistrationBean.setFilter(targetFilter);
filterRegistrationBean.setOrder(filterOrder);
filterRegistrationBean.setInitParameters(initParams);
if (urlPatterns.size() > 0) {
filterRegistrationBean.setUrlPatterns(urlPatterns);
}
}
但是比较诡异的是,貌似该注解下没有SingleSignOutFilter过滤器,我暂时还没有搞清楚。不过可以继承CasClientConfigurerAdapter类进行自定义。