Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

reworked logout filter configuration

  • Loading branch information...
commit 51d05c3ac39e5bd22b8eff14aa6e1a9a121fc4a0 1 parent 33799f6
@burtbeckwith burtbeckwith authored
View
1  .classpath
@@ -13,6 +13,5 @@
<classpathentry kind="var" path="IVY_CACHE/org.springframework.security/org.springframework.security.core/jars/org.springframework.security.core-3.0.2.RELEASE.jar" sourcepath="/SPRING_SECURITY_SOURCE/spring-security-core-3.0.2.RELEASE-sources.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework.security/org.springframework.security.web/jars/org.springframework.security.web-3.0.2.RELEASE.jar" sourcepath="/SPRING_SECURITY_SOURCE/spring-security-web-3.0.2.RELEASE-sources.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/grails1.2"/>
- <classpathentry kind="lib" path="lib/easymock.jar"/>
<classpathentry kind="output" path="target/eclipseclasses"/>
</classpath>
View
29 SpringSecurityCoreGrailsPlugin.groovy
@@ -52,6 +52,7 @@ import org.springframework.security.web.authentication.AnonymousAuthenticationFi
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler
+import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler
import org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter
@@ -85,7 +86,7 @@ import org.codehaus.groovy.grails.plugins.springsecurity.GormPersistentTokenRepo
import org.codehaus.groovy.grails.plugins.springsecurity.GormUserDetailsService
import org.codehaus.groovy.grails.plugins.springsecurity.InterceptUrlMapFilterInvocationDefinition
import org.codehaus.groovy.grails.plugins.springsecurity.IpAddressFilter
-import org.codehaus.groovy.grails.plugins.springsecurity.LogoutFilterFactoryBean
+import org.codehaus.groovy.grails.plugins.springsecurity.MutableLogoutFilter
import org.codehaus.groovy.grails.plugins.springsecurity.NullSaltSource
import org.codehaus.groovy.grails.plugins.springsecurity.RequestmapFilterInvocationDefinition
import org.codehaus.groovy.grails.plugins.springsecurity.RequestHolderAuthenticationFilter
@@ -96,15 +97,13 @@ import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
class SpringSecurityCoreGrailsPlugin {
- String version = '0.2'
+ String version = '0.2.1'
String grailsVersion = '1.2.2 > *'
List observe = ['controllers']
List loadAfter = ['controllers', 'services', 'hibernate']
List pluginExcludes = [
- 'lib/easymock*.jar',
'grails-app/domain/**',
- 'grails-app/services/**/Test*Service.groovy',
'scripts/_Events.groovy',
'scripts/CreateTestApp.groovy',
'docs/**',
@@ -341,6 +340,9 @@ class SpringSecurityCoreGrailsPlugin {
transactionManager = ref('transactionManager')
}
+ /** authenticationUserDetailsService */
+ authenticationUserDetailsService(UserDetailsByNameServiceWrapper, ref('userDetailsService'))
+
// port mappings for channel security, etc.
portMapper(PortMapperImpl) {
portMappings = [(conf.portMapper.httpPort.toString()) : conf.portMapper.httpsPort.toString()]
@@ -550,13 +552,16 @@ class SpringSecurityCoreGrailsPlugin {
securityContextLogoutHandler(SecurityContextLogoutHandler)
- // create a dummy list here, will be replaced in doWithApplicationContext
- logoutHandlers(ArrayList, [new SecurityContextLogoutHandler()])
+ // create an initially empty list here, will be populated in doWithApplicationContext
+ logoutHandlers(ArrayList)
+
+ logoutSuccessHandler(SimpleUrlLogoutSuccessHandler) {
+ redirectStrategy = ref('redirectStrategy')
+ defaultTargetUrl = conf.logout.afterLogoutUrl // '/'
+ }
/** logoutFilter */
- logoutFilter(LogoutFilterFactoryBean) {
- handlers = logoutHandlers
- logoutSuccessUrl = conf.logout.afterLogoutUrl // '/'
+ logoutFilter(MutableLogoutFilter, ref('logoutSuccessHandler')) {
filterProcessesUrl = conf.logout.filterProcessesUrl // '/j_spring_security_logout'
}
}
@@ -834,14 +839,10 @@ class SpringSecurityCoreGrailsPlugin {
subjectDnRegex = conf.x509.subjectDnRegex // CN=(.*?),
}
- preAuthenticatedUserDetailsService(UserDetailsByNameServiceWrapper) {
- userDetailsService = ref('userDetailsService')
- }
-
userDetailsChecker(AccountStatusUserDetailsChecker)
x509AuthenticationProvider(PreAuthenticatedAuthenticationProvider) {
- preAuthenticatedUserDetailsService = ref('preAuthenticatedUserDetailsService')
+ preAuthenticatedUserDetailsService = ref('authenticationUserDetailsService')
userDetailsChecker = ref('userDetailsChecker')
throwExceptionWhenTokenRejected = conf.x509.throwExceptionWhenTokenRejected // false
}
View
BIN  lib/easymock.jar
Binary file not shown
View
4 scripts/CreateTestApp.groovy → scripts/CreateS2TestApps.groovy
@@ -10,7 +10,7 @@ pluginVersion = null
pluginZip = null
testprojectRoot = null
-target(createTestApp: 'Creates test apps for functional tests') {
+target(createS2TestApp: 'Creates test apps for functional tests') {
def configFile = new File(basedir, 'testapps.config.groovy')
if (!configFile.exists()) {
@@ -177,4 +177,4 @@ private void error(String message) {
exit 1
}
-setDefaultTarget 'createTestApp'
+setDefaultTarget 'createS2TestApp'
View
106 src/java/org/codehaus/groovy/grails/plugins/springsecurity/LogoutFilterFactoryBean.java
@@ -1,106 +0,0 @@
-/* Copyright 2006-2010 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.codehaus.groovy.grails.plugins.springsecurity;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.springframework.beans.factory.FactoryBean;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.security.web.authentication.logout.LogoutFilter;
-import org.springframework.security.web.authentication.logout.LogoutHandler;
-import org.springframework.util.Assert;
-
-/**
- * Configures a {@link LogoutFilter} given a list of {@link LogoutHandler}s.
- *
- * @author <a href='mailto:burt@burtbeckwith.com'>Burt Beckwith</a>
- */
-public class LogoutFilterFactoryBean implements FactoryBean<LogoutFilter>, InitializingBean {
-
- private List<LogoutHandler> _handlers;
- private LogoutFilter _logoutFilter;
- private String _logoutSuccessUrl;
- private String _filterProcessesUrl;
-
- /**
- * {@inheritDoc}
- * @see org.springframework.beans.factory.FactoryBean#getObject()
- */
- public LogoutFilter getObject() {
- return _logoutFilter;
- }
-
- /**
- * {@inheritDoc}
- * @see org.springframework.beans.factory.FactoryBean#getObjectType()
- */
- public Class<LogoutFilter> getObjectType() {
- return LogoutFilter.class;
- }
-
- /**
- * {@inheritDoc}
- * @see org.springframework.beans.factory.FactoryBean#isSingleton()
- */
- public boolean isSingleton() {
- return true;
- }
-
- /**
- * {@inheritDoc}
- * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
- */
- public void afterPropertiesSet() {
- Assert.notNull(_logoutSuccessUrl, "logoutSuccessUrl is required");
- Assert.notNull(_handlers, "handlers are required");
-
- _logoutFilter = new LogoutFilter(_logoutSuccessUrl,
- _handlers.toArray(new LogoutHandler[_handlers.size()]));
- _logoutFilter.setFilterProcessesUrl(_filterProcessesUrl);
- }
-
- /**
- * Dependency injection for the logout success url.
- * @param url the url
- */
- public void setLogoutSuccessUrl(final String url) {
- _logoutSuccessUrl = url;
- }
-
- /**
- * Dependency injection for 'filterProcessesUrl.
- * @param url the url
- */
- public void setFilterProcessesUrl(final String url) {
- _filterProcessesUrl = url;
- }
-
- /**
- * Dependency injection for the handlers.
- * @param handlers the handlers
- */
- public void setHandlers(final List<LogoutHandler> handlers) {
- _handlers = handlers;
- }
-
- /**
- * For debugging.
- * @return the handlers
- */
- public List<LogoutHandler> getHandlers() {
- return Collections.unmodifiableList(_handlers);
- }
-}
View
101 src/java/org/codehaus/groovy/grails/plugins/springsecurity/MutableLogoutFilter.java
@@ -0,0 +1,101 @@
+/* Copyright 2006-2010 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.codehaus.groovy.grails.plugins.springsecurity;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.logout.LogoutFilter;
+import org.springframework.security.web.authentication.logout.LogoutHandler;
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
+import org.springframework.util.Assert;
+
+/**
+ * @author <a href='mailto:burt@burtbeckwith.com'>Burt Beckwith</a>
+ */
+public class MutableLogoutFilter extends LogoutFilter {
+
+ private final LogoutSuccessHandler _logoutSuccessHandler;
+
+ private List<LogoutHandler> _handlers;
+
+ /**
+ * Constructor.
+ * @param logoutSuccessHandler the logout success handler
+ */
+ public MutableLogoutFilter(LogoutSuccessHandler logoutSuccessHandler) {
+ super(logoutSuccessHandler, new DummyLogoutHandler());
+ _logoutSuccessHandler = logoutSuccessHandler;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see org.springframework.security.web.authentication.logout.LogoutFilter#doFilter(
+ * javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
+ */
+ @Override
+ public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain)
+ throws IOException, ServletException {
+
+ HttpServletRequest request = (HttpServletRequest) req;
+ HttpServletResponse response = (HttpServletResponse) res;
+
+ if (requiresLogout(request, response)) {
+ Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Logging out user '" + auth + "' and transferring to logout destination");
+ }
+
+ for (LogoutHandler handler : _handlers) {
+ handler.logout(request, response, auth);
+ }
+
+ _logoutSuccessHandler.onLogoutSuccess(request, response, auth);
+
+ return;
+ }
+
+ chain.doFilter(request, response);
+ }
+
+ /**
+ * Dependency injection for the logout handlers.
+ * @param handlers the handlers
+ */
+ public void setHandlers(final List<LogoutHandler> handlers) {
+ Assert.notEmpty(handlers, "LogoutHandlers are required");
+ _handlers = handlers;
+ }
+
+ /**
+ * Null logout handler that's used to provide a non-empty list of handlers to the base class.
+ * The real handlers will be after construction.
+ */
+ private static class DummyLogoutHandler implements LogoutHandler {
+ public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
+ // do nothing
+ }
+ }
+}
View
106 ...nit/org/codehaus/groovy/grails/plugins/springsecurity/LogoutFilterFactoryBeanTests.groovy
@@ -1,106 +0,0 @@
-/* Copyright 2006-2010 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.codehaus.groovy.grails.plugins.springsecurity
-
-import javax.servlet.FilterChain
-import javax.servlet.http.HttpServletRequest
-import javax.servlet.http.HttpServletResponse
-
-import org.easymock.EasyMock
-import org.springframework.mock.web.MockHttpServletRequest
-import org.springframework.mock.web.MockHttpServletResponse
-import org.springframework.security.core.Authentication
-import org.springframework.security.web.authentication.logout.LogoutFilter
-import org.springframework.security.web.authentication.logout.LogoutHandler
-
-/**
- * Unit tests for <code>LogoutFilterFactoryBean</code>.
- *
- * @author <a href='mailto:burt@burtbeckwith.com'>Burt Beckwith</a>
- */
-class LogoutFilterFactoryBeanTests extends GroovyTestCase {
-
- private final LogoutFilterFactoryBean _factory = new LogoutFilterFactoryBean()
-
- /**
- * Test isSingleton.
- */
- void testIsSingleton() {
- assertTrue _factory.singleton
- }
-
- /**
- * Test building a filter.
- */
- void testFactory() {
- String url = '/after_logout'
- String filterProcessesUrl = '/j_spring_security_logout'
-
- Authentication authentication = SecurityTestUtils.authenticate()
-
- def request1 = new MockHttpServletRequest('GET', '/foo/bar')
- def response1 = new MockHttpServletResponse()
- def request2 = new MockHttpServletRequest('GET', filterProcessesUrl)
- def response2 = new MockHttpServletResponse()
-
- def handlers = []
- (1..5).each { handlers << EasyMock.createMock(LogoutHandler) }
- handlers.each { handler ->
- handler.logout(request2, response2, authentication)
- EasyMock.replay(handler)
- }
-
- _factory.logoutSuccessUrl = url
- _factory.handlers = handlers
- _factory.filterProcessesUrl = filterProcessesUrl
- assertNull _factory.object
-
- _factory.afterPropertiesSet()
-
- assertNotNull _factory.object
- assertEquals LogoutFilter, _factory.objectType
- assertTrue _factory.object instanceof LogoutFilter
-
- // now test the filter to ensure that it calls the handlers
-
- LogoutFilter filter = _factory.object
-
- FilterChain chain1 = EasyMock.createMock(FilterChain)
- FilterChain chain2 = EasyMock.createMock(FilterChain)
- chain1.doFilter(request1, response1)
- EasyMock.expectLastCall()
- EasyMock.replay(chain1, chain2)
-
- // not a logout url, so chain.doFilter() is called
- filter.doFilter(request1, response1, chain1)
- assertNull response1.redirectedUrl
-
- filter.doFilter(request2, response2, chain2)
- assertNotNull response2.redirectedUrl
-
- EasyMock.verify(handlers as Object[])
- EasyMock.verify(chain1, chain2)
- }
-
- /**
- * {@inheritDoc}
- * @see junit.framework.TestCase#tearDown()
- */
- @Override
- protected void tearDown() {
- super.tearDown()
- SecurityTestUtils.logout()
- }
-}
View
76 test/unit/org/codehaus/groovy/grails/plugins/springsecurity/MutableLogoutFilterTests.groovy
@@ -0,0 +1,76 @@
+/* Copyright 2006-2010 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.codehaus.groovy.grails.plugins.springsecurity
+
+import javax.servlet.FilterChain
+
+import org.springframework.mock.web.MockHttpServletRequest
+import org.springframework.mock.web.MockHttpServletResponse
+import org.springframework.security.web.authentication.logout.LogoutHandler
+import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler
+
+/**
+ * Unit tests for MutableLogoutFilter.
+ *
+ * @author <a href='mailto:burt@burtbeckwith.com'>Burt Beckwith</a>
+ */
+class MutableLogoutFilterTests extends GroovyTestCase {
+
+ private final String _afterLogoutUrl = '/loggedout'
+ private final _logoutSuccessHandler = new SimpleUrlLogoutSuccessHandler(
+ defaultTargetUrl: _afterLogoutUrl)
+ private final _handlers = []
+ private final _filter = new MutableLogoutFilter(_logoutSuccessHandler)
+
+ private int _logoutCount
+
+ @Override
+ protected void setUp() {
+ super.setUp()
+ (1..5).each {
+ def handler = [logout: { req, res, auth -> _logoutCount++ }] as LogoutHandler
+ _handlers << handler
+ }
+ _filter.handlers = _handlers
+ }
+
+ void testDoFilter() {
+ String url = '/after_logout'
+ String filterProcessesUrl = '/j_spring_security_logout'
+
+ def authentication = SecurityTestUtils.authenticate()
+
+ def request1 = new MockHttpServletRequest('GET', '/foo/bar')
+ def response1 = new MockHttpServletResponse()
+ def request2 = new MockHttpServletRequest('GET', filterProcessesUrl)
+ def response2 = new MockHttpServletResponse()
+
+ boolean chain1Called = false
+ boolean chain2Called = false
+ def chain1 = [doFilter: { req, res -> chain1Called = true }] as FilterChain
+ def chain2 = [doFilter: { req, res -> chain2Called = true }] as FilterChain
+
+ // not a logout url, so chain.doFilter() is called
+ _filter.doFilter request1, response1, chain1
+ assertNull response1.redirectedUrl
+
+ _filter.doFilter request2, response2, chain2
+ assertNotNull response2.redirectedUrl
+
+ assertTrue chain1Called
+ assertFalse chain2Called
+ assertEquals 5, _logoutCount
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.