Author: pledbrook Date: Mon Feb 1 11:27:04 2010 New Revision: 905255 URL: http://svn.apache.org/viewvc?rev=905255&view=rev Log: Fix for SHIRO-130: I have introduced a WebSecurityManager interface that the servlet filter classes use. This fixes the problem with proxies because they can now proxy the new interface and provide the isHttpSessionMode() method. This also fixes:
http://jira.codehaus.org/browse/GRAILSPLUGINS-1742 Added: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebSecurityManager.java Modified: incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/web/ShiroFilterFactoryBean.java incubator/shiro/trunk/support/spring/src/test/java/org/apache/shiro/spring/SpringShiroFilterTest.java incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DefaultWebSecurityManager.java incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/AbstractShiroFilter.java incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/IniShiroFilter.java incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java Modified: incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/web/ShiroFilterFactoryBean.java URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/web/ShiroFilterFactoryBean.java?rev=905255&r1=905254&r2=905255&view=diff ============================================================================== --- incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/web/ShiroFilterFactoryBean.java (original) +++ incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/web/ShiroFilterFactoryBean.java Mon Feb 1 11:27:04 2010 @@ -23,6 +23,7 @@ import org.apache.shiro.util.CollectionUtils; import org.apache.shiro.util.Nameable; import org.apache.shiro.util.StringUtils; +import org.apache.shiro.web.WebSecurityManager; import org.apache.shiro.web.config.IniFilterChainResolverFactory; import org.apache.shiro.web.filter.AccessControlFilter; import org.apache.shiro.web.filter.authc.AuthenticationFilter; @@ -423,6 +424,11 @@ String msg = "SecurityManager property must be set."; throw new BeanInitializationException(msg); } + + if (!(securityManager instanceof WebSecurityManager)) { + String msg = "The security manager does not implement the WebSecurityManager interface."; + throw new BeanInitializationException(msg); + } FilterChainManager manager = createFilterChainManager(); @@ -437,7 +443,7 @@ //here - we're just using it because it is a concrete ShiroFilter instance that accepts //injection of the SecurityManager and FilterChainResolver: IniShiroFilter shiroFilter = new IniShiroFilter(); - shiroFilter.setSecurityManager(securityManager); + shiroFilter.setSecurityManager((WebSecurityManager) securityManager); shiroFilter.setFilterChainResolver(chainResolver); return shiroFilter; Modified: incubator/shiro/trunk/support/spring/src/test/java/org/apache/shiro/spring/SpringShiroFilterTest.java URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/support/spring/src/test/java/org/apache/shiro/spring/SpringShiroFilterTest.java?rev=905255&r1=905254&r2=905255&view=diff ============================================================================== --- incubator/shiro/trunk/support/spring/src/test/java/org/apache/shiro/spring/SpringShiroFilterTest.java (original) +++ incubator/shiro/trunk/support/spring/src/test/java/org/apache/shiro/spring/SpringShiroFilterTest.java Mon Feb 1 11:27:04 2010 @@ -18,14 +18,22 @@ */ package org.apache.shiro.spring; +import org.apache.shiro.config.ConfigurationException; import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.web.WebSecurityManager; import org.apache.shiro.web.servlet.ShiroFilter; + import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import org.junit.Test; import org.springframework.web.context.WebApplicationContext; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; +import javax.servlet.ServletException; + import java.util.HashMap; import java.util.Map; @@ -49,7 +57,7 @@ ServletContext mockContext = createMock(ServletContext.class); WebApplicationContext appCtx = createMock(WebApplicationContext.class); - SecurityManager secMgr = createMock(SecurityManager.class); + SecurityManager secMgr = createMock(WebSecurityManager.class); Map<String, org.apache.shiro.mgt.SecurityManager> beansOfType = new HashMap<String, SecurityManager>(1); beansOfType.put("securityManager", secMgr); @@ -65,4 +73,43 @@ filter.init(mockConfig); } + + @Test + public void testDefaultConfigWithNonWebSecurityManager() throws Exception { + SpringShiroFilter filter = new SpringShiroFilter(); + + FilterConfig mockConfig = createMock(FilterConfig.class); + expect(mockConfig.getInitParameter(ShiroFilter.CONFIG_CLASS_NAME_INIT_PARAM_NAME)).andReturn(null); + expect(mockConfig.getInitParameter(ShiroFilter.CONFIG_INIT_PARAM_NAME)).andReturn(null); + expect(mockConfig.getInitParameter(ShiroFilter.CONFIG_URL_INIT_PARAM_NAME)).andReturn(null); + expect(mockConfig.getInitParameter(SpringIniWebConfiguration.SECURITY_MANAGER_BEAN_NAME_PARAM_NAME)).andReturn(null); + + ServletContext mockContext = createMock(ServletContext.class); + WebApplicationContext appCtx = createMock(WebApplicationContext.class); + SecurityManager secMgr = createMock(SecurityManager.class); + Map<String, org.apache.shiro.mgt.SecurityManager> beansOfType = new HashMap<String, SecurityManager>(1); + beansOfType.put("securityManager", secMgr); + + expect(mockContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)).andReturn(appCtx); + expect(appCtx.getBeansOfType(SecurityManager.class)).andReturn(beansOfType); + + expect(mockConfig.getServletContext()).andReturn(mockContext).anyTimes(); + + + replay(mockContext); + replay(appCtx); + replay(mockConfig); + + try { + filter.init(mockConfig); + fail("ServletException (wrapping a ConfigurationException) expected because the security manager " + + "does not implement WebSecurityManager."); + } + catch (ServletException ex) { + // The cause should be a ConfigurationException. + assertTrue( + "Original cause is not a ConfigurationException as expected", + ex.getCause() instanceof ConfigurationException); + } + } } Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DefaultWebSecurityManager.java URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DefaultWebSecurityManager.java?rev=905255&r1=905254&r2=905255&view=diff ============================================================================== --- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DefaultWebSecurityManager.java (original) +++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DefaultWebSecurityManager.java Mon Feb 1 11:27:04 2010 @@ -47,7 +47,7 @@ * @author Les Hazlewood * @since 0.2 */ -public class DefaultWebSecurityManager extends DefaultSecurityManager { +public class DefaultWebSecurityManager extends DefaultSecurityManager implements WebSecurityManager { //TODO - complete JavaDoc Added: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebSecurityManager.java URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebSecurityManager.java?rev=905255&view=auto ============================================================================== --- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebSecurityManager.java (added) +++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebSecurityManager.java Mon Feb 1 11:27:04 2010 @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.web; + +import org.apache.shiro.mgt.SecurityManager; +/** + * This interface represents a {...@link SecurityManager} implementation that can + * be used in a servlet container. + * + * @author Peter Ledbrook + * @since 1.0 + */ +public interface WebSecurityManager extends SecurityManager { + /** + * Security information needs to be retained from request to request, so Shiro makes use of a + * session for this. Typically, a security manager will use the servlet container's HTTP session + * but custom session implementations, for example based on EhCache, may also be used. This + * method indicates whether the security manager is using the HTTP session or not. + * @return <code>true</code> if the security manager is using the HTTP session; otherwise, + * <code>false</code>. + */ + boolean isHttpSessionMode(); +} Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/AbstractShiroFilter.java URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/AbstractShiroFilter.java?rev=905255&r1=905254&r2=905255&view=diff ============================================================================== --- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/AbstractShiroFilter.java (original) +++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/AbstractShiroFilter.java Mon Feb 1 11:27:04 2010 @@ -19,12 +19,12 @@ package org.apache.shiro.web.servlet; import org.apache.shiro.SecurityUtils; -import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.ThreadContext; import org.apache.shiro.util.ThreadState; import org.apache.shiro.web.DefaultWebSecurityManager; +import org.apache.shiro.web.WebSecurityManager; import org.apache.shiro.web.WebUtils; import org.apache.shiro.web.filter.mgt.FilterChainResolver; import org.apache.shiro.web.subject.WebSubject; @@ -57,7 +57,7 @@ private static final Logger log = LoggerFactory.getLogger(AbstractShiroFilter.class); // Reference to the security manager used by this filter - private SecurityManager securityManager; + private WebSecurityManager securityManager; // Used to determine which chain should handle an incoming request/response private FilterChainResolver filterChainResolver; @@ -65,11 +65,11 @@ protected AbstractShiroFilter() { } - public SecurityManager getSecurityManager() { + public WebSecurityManager getSecurityManager() { return securityManager; } - public void setSecurityManager(SecurityManager sm) { + public void setSecurityManager(WebSecurityManager sm) { this.securityManager = sm; } @@ -95,7 +95,7 @@ * creates one automatically. */ private void ensureSecurityManager() { - SecurityManager securityManager = getSecurityManager(); + WebSecurityManager securityManager = getSecurityManager(); if (securityManager == null) { log.info("No SecurityManager configured. Creating default."); securityManager = createDefaultSecurityManager(); @@ -103,13 +103,12 @@ } } - protected SecurityManager createDefaultSecurityManager() { + protected WebSecurityManager createDefaultSecurityManager() { return new DefaultWebSecurityManager(); } protected boolean isHttpSessions() { - SecurityManager secMgr = getSecurityManager(); - return !(secMgr instanceof DefaultWebSecurityManager) || ((DefaultWebSecurityManager) secMgr).isHttpSessionMode(); + return getSecurityManager().isHttpSessionMode(); } /** Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/IniShiroFilter.java URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/IniShiroFilter.java?rev=905255&r1=905254&r2=905255&view=diff ============================================================================== --- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/IniShiroFilter.java (original) +++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/IniShiroFilter.java Mon Feb 1 11:27:04 2010 @@ -18,10 +18,12 @@ */ package org.apache.shiro.web.servlet; +import org.apache.shiro.config.ConfigurationException; import org.apache.shiro.config.Ini; import org.apache.shiro.config.IniFactorySupport; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.util.Factory; +import org.apache.shiro.web.WebSecurityManager; import org.apache.shiro.web.config.IniFilterChainResolverFactory; import org.apache.shiro.web.config.WebIniSecurityManagerFactory; import org.apache.shiro.web.filter.mgt.FilterChainResolver; @@ -343,8 +345,17 @@ } else { factory = new WebIniSecurityManagerFactory(ini); } + + // Create the security manager and check that it implements WebSecurityManager. + // Otherwise, it can't be used with the filter. SecurityManager securityManager = factory.getInstance(); - setSecurityManager(securityManager); + if (!(securityManager instanceof WebSecurityManager)) { + String msg = "The configured security manager is not an instance of WebSecurityManager, so " + + "it can not be used with the Shiro servlet filter."; + throw new ConfigurationException(msg); + } + + setSecurityManager((WebSecurityManager) securityManager); } protected void applyFilterChainResolver(Ini ini) { Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java?rev=905255&r1=905254&r2=905255&view=diff ============================================================================== --- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java (original) +++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java Mon Feb 1 11:27:04 2010 @@ -30,6 +30,7 @@ import org.apache.shiro.util.ThreadContext; import org.apache.shiro.util.ThreadState; import org.apache.shiro.web.DefaultWebSecurityManager; +import org.apache.shiro.web.WebSecurityManager; import org.apache.shiro.web.WebUtils; import org.apache.shiro.web.config.IniWebConfiguration; import org.apache.shiro.web.config.WebConfiguration; @@ -254,7 +255,7 @@ protected WebConfiguration configuration; // Reference to the security manager used by this filter - protected SecurityManager securityManager; + protected WebSecurityManager securityManager; // Used to determine which chain should handle an incoming request/response private FilterChainResolver filterChainResolver; @@ -271,11 +272,11 @@ this.configuration = configuration; } - public SecurityManager getSecurityManager() { + public WebSecurityManager getSecurityManager() { return securityManager; } - protected void setSecurityManager(SecurityManager sm) { + protected void setSecurityManager(WebSecurityManager sm) { this.securityManager = sm; } @@ -302,10 +303,18 @@ * @param config the configuration for this filter. */ protected void ensureSecurityManager(Configuration config) { - SecurityManager securityManager = getSecurityManager(); + WebSecurityManager securityManager = getSecurityManager(); boolean existing = securityManager != null; if (!existing && config != null) { - securityManager = config.getSecurityManager(); + // Get the configured security manager. If it isn't an implementation of + // WebSecurityManager, then we raise an error. + SecurityManager sm = config.getSecurityManager(); + if (!(sm instanceof WebSecurityManager)) { + String msg = "The configured security manager is not an instance of WebSecurityManager, so " + + "it can not be used with the Shiro servlet filter."; + throw new ConfigurationException(msg); + } + securityManager = (WebSecurityManager) sm; } // If the config doesn't return a security manager, build one by default. @@ -420,8 +429,7 @@ } protected boolean isHttpSessions() { - SecurityManager secMgr = getSecurityManager(); - return !(secMgr instanceof DefaultWebSecurityManager) || ((DefaultWebSecurityManager) secMgr).isHttpSessionMode(); + return getSecurityManager().isHttpSessionMode(); } /**
