/* * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.config.http; import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler; import org.springframework.security.web.authentication.logout.LogoutFilter; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** * @author Luke Taylor * @author Ben Alex */ class LogoutBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_LOGOUT_SUCCESS_URL = "logout-success-url"; static final String ATT_INVALIDATE_SESSION = "invalidate-session"; static final String ATT_LOGOUT_URL = "logout-url"; static final String DEF_LOGOUT_URL = "/logout"; static final String ATT_LOGOUT_HANDLER = "success-handler-ref"; static final String ATT_DELETE_COOKIES = "delete-cookies"; final String rememberMeServices; private final String defaultLogoutUrl; private ManagedList<BeanMetadataElement> logoutHandlers = new ManagedList<BeanMetadataElement>(); private boolean csrfEnabled; public LogoutBeanDefinitionParser(String loginPageUrl, String rememberMeServices, BeanMetadataElement csrfLogoutHandler) { this.defaultLogoutUrl = loginPageUrl + "?logout"; this.rememberMeServices = rememberMeServices; this.csrfEnabled = csrfLogoutHandler != null; if (this.csrfEnabled) { logoutHandlers.add(csrfLogoutHandler); } } public BeanDefinition parse(Element element, ParserContext pc) { String logoutUrl = null; String successHandlerRef = null; String logoutSuccessUrl = null; String invalidateSession = null; String deleteCookies = null; BeanDefinitionBuilder builder = BeanDefinitionBuilder .rootBeanDefinition(LogoutFilter.class); if (element != null) { Object source = pc.extractSource(element); builder.getRawBeanDefinition().setSource(source); logoutUrl = element.getAttribute(ATT_LOGOUT_URL); successHandlerRef = element.getAttribute(ATT_LOGOUT_HANDLER); WebConfigUtils.validateHttpRedirect(logoutUrl, pc, source); logoutSuccessUrl = element.getAttribute(ATT_LOGOUT_SUCCESS_URL); WebConfigUtils.validateHttpRedirect(logoutSuccessUrl, pc, source); invalidateSession = element.getAttribute(ATT_INVALIDATE_SESSION); deleteCookies = element.getAttribute(ATT_DELETE_COOKIES); } if (!StringUtils.hasText(logoutUrl)) { logoutUrl = DEF_LOGOUT_URL; } builder.addPropertyValue("logoutRequestMatcher", getLogoutRequestMatcher(logoutUrl)); if (StringUtils.hasText(successHandlerRef)) { if (StringUtils.hasText(logoutSuccessUrl)) { pc.getReaderContext().error( "Use " + ATT_LOGOUT_SUCCESS_URL + " or " + ATT_LOGOUT_HANDLER + ", but not both", pc.extractSource(element)); } builder.addConstructorArgReference(successHandlerRef); } else { // Use the logout URL if no handler set if (!StringUtils.hasText(logoutSuccessUrl)) { logoutSuccessUrl = defaultLogoutUrl; } builder.addConstructorArgValue(logoutSuccessUrl); } BeanDefinition sclh = new RootBeanDefinition(SecurityContextLogoutHandler.class); sclh.getPropertyValues().addPropertyValue("invalidateHttpSession", !"false".equals(invalidateSession)); logoutHandlers.add(sclh); if (rememberMeServices != null) { logoutHandlers.add(new RuntimeBeanReference(rememberMeServices)); } if (StringUtils.hasText(deleteCookies)) { BeanDefinition cookieDeleter = new RootBeanDefinition( CookieClearingLogoutHandler.class); String[] names = StringUtils.tokenizeToStringArray(deleteCookies, ","); cookieDeleter.getConstructorArgumentValues().addGenericArgumentValue(names); logoutHandlers.add(cookieDeleter); } builder.addConstructorArgValue(logoutHandlers); return builder.getBeanDefinition(); } private BeanDefinition getLogoutRequestMatcher(String logoutUrl) { BeanDefinitionBuilder matcherBuilder = BeanDefinitionBuilder .rootBeanDefinition("org.springframework.security.web.util.matcher.AntPathRequestMatcher"); matcherBuilder.addConstructorArgValue(logoutUrl); if (this.csrfEnabled) { matcherBuilder.addConstructorArgValue("POST"); } return matcherBuilder.getBeanDefinition(); } ManagedList<BeanMetadataElement> getLogoutHandlers() { return logoutHandlers; } }