package net.unicon.cas.client.configuration; import org.jasig.cas.client.authentication.AuthenticationFilter; import org.jasig.cas.client.authentication.Saml11AuthenticationFilter; import org.jasig.cas.client.util.AssertionThreadLocalFilter; import org.jasig.cas.client.util.HttpServletRequestWrapperFilter; import org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter; import org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter; import org.jasig.cas.client.validation.Saml11TicketValidationFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import javax.servlet.Filter; import static net.unicon.cas.client.configuration.EnableCasClient.ValidationType.CAS; import static net.unicon.cas.client.configuration.EnableCasClient.ValidationType.CAS3; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Configuration class providing default CAS client infrastructure filters. * This configuration facility is typically imported into Spring's Application Context via * {@link net.unicon.cas.client.configuration.EnableCasClient EnableCasClient} meta annotation. * * @author Dmitriy Kopylenko * @see net.unicon.cas.client.configuration.EnableCasClient * @since 1.0.0 */ @Configuration @EnableConfigurationProperties(CasClientConfigurationProperties.class) public class CasClientConfiguration { @Autowired CasClientConfigurationProperties configProps; private CasClientConfigurer casClientConfigurer; @Bean @ConditionalOnProperty(prefix = "cas", name = "skipTicketValidation", havingValue = "false", matchIfMissing = true) public FilterRegistrationBean casValidationFilter() { final FilterRegistrationBean validationFilter = new FilterRegistrationBean(); final Filter targetCasValidationFilter; switch (this.configProps.getValidationType()) { case CAS: targetCasValidationFilter = new Cas20ProxyReceivingTicketValidationFilter(); break; case CAS3: targetCasValidationFilter = new Cas30ProxyReceivingTicketValidationFilter(); break; case SAML: targetCasValidationFilter = new Saml11TicketValidationFilter(); break; default: throw new IllegalStateException("Unknown CAS validation type"); } initFilter(validationFilter, targetCasValidationFilter, 1, constructInitParams("casServerUrlPrefix", this.configProps.getServerUrlPrefix(), this.configProps.getClientHostUrl()), this.configProps.getValidationUrlPatterns()); if (this.configProps.getUseSession() != null) { validationFilter.getInitParameters().put("useSession", String.valueOf(this.configProps.getUseSession())); } if (this.configProps.getRedirectAfterValidation() != null) { validationFilter.getInitParameters().put("redirectAfterValidation", String.valueOf(this.configProps.getRedirectAfterValidation())); } //Proxy tickets validation if (this.configProps.getAcceptAnyProxy() != null) { validationFilter.getInitParameters().put("acceptAnyProxy", String.valueOf(this.configProps.getAcceptAnyProxy())); } if (this.configProps.getAllowedProxyChains().size() > 0) { validationFilter.getInitParameters().put("allowedProxyChains", StringUtils.collectionToDelimitedString(this.configProps.getAllowedProxyChains(), " ")); } if (this.configProps.getProxyCallbackUrl() != null) { validationFilter.getInitParameters().put("proxyCallbackUrl", this.configProps.getProxyCallbackUrl()); } if (this.configProps.getProxyReceptorUrl() != null) { validationFilter.getInitParameters().put("proxyReceptorUrl", this.configProps.getProxyReceptorUrl()); } if (this.casClientConfigurer != null) { this.casClientConfigurer.configureValidationFilter(validationFilter); } return validationFilter; } @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); } } }