diff --git a/core/src/test/java/org/acegisecurity/MockFilterChain.java b/core/src/test/java/org/acegisecurity/MockFilterChain.java new file mode 100644 index 0000000000..b2139bc19c --- /dev/null +++ b/core/src/test/java/org/acegisecurity/MockFilterChain.java @@ -0,0 +1,39 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + + +/** + * Mocks a FilterChain but with no behaviour. + * + * @author Ben Alex + * @version $Id$ + */ +public class MockFilterChain implements FilterChain { + //~ Methods ================================================================ + + public void doFilter(ServletRequest arg0, ServletResponse arg1) + throws IOException, ServletException { + throw new UnsupportedOperationException("mock method not implemented"); + } +} diff --git a/core/src/test/java/org/acegisecurity/MockFilterConfig.java b/core/src/test/java/org/acegisecurity/MockFilterConfig.java new file mode 100644 index 0000000000..ea36eb5644 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/MockFilterConfig.java @@ -0,0 +1,64 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity; + +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.FilterConfig; +import javax.servlet.ServletContext; + + +/** + * DOCUMENT ME! + * + * @author Ben Alex + * @version $Id$ + */ +public class MockFilterConfig implements FilterConfig { + //~ Instance fields ======================================================== + + private Map map = new HashMap(); + + //~ Methods ================================================================ + + public String getFilterName() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getInitParameter(String arg0) { + Object result = map.get(arg0); + + if (result != null) { + return (String) result; + } else { + return null; + } + } + + public Enumeration getInitParameterNames() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void setInitParmeter(String parameter, String value) { + map.put(parameter, value); + } + + public ServletContext getServletContext() { + throw new UnsupportedOperationException("mock method not implemented"); + } +} diff --git a/core/src/test/java/org/acegisecurity/MockHttpServletRequest.java b/core/src/test/java/org/acegisecurity/MockHttpServletRequest.java new file mode 100644 index 0000000000..c5a9acb684 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/MockHttpServletRequest.java @@ -0,0 +1,291 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity; + +import java.io.BufferedReader; +import java.io.IOException; + +import java.security.Principal; + +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletInputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + + +/** + * Mocks a HttpServletRequest and provides the + * getUserPrincipal(), getContextPath(), + * getServletPath() and getSession() methods. + * + *

+ * Also provides a convenience Map for storing request parameters. + *

+ * + * @author Ben Alex + * @version $Id$ + */ +public class MockHttpServletRequest implements HttpServletRequest { + //~ Instance fields ======================================================== + + private HttpSession session; + private Map map = new HashMap(); + private Principal principal; + private String contextPath = ""; + private String queryString = null; + private String servletPath; + + //~ Constructors =========================================================== + + public MockHttpServletRequest(Principal principal, HttpSession session) { + this.principal = principal; + this.session = session; + } + + public MockHttpServletRequest(String queryString) { + this.queryString = queryString; + } + + private MockHttpServletRequest() { + super(); + } + + //~ Methods ================================================================ + + public void setAttribute(String arg0, Object arg1) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Object getAttribute(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Enumeration getAttributeNames() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getAuthType() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void setCharacterEncoding(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getCharacterEncoding() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public int getContentLength() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getContentType() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void setContextPath(String contextPath) { + this.contextPath = contextPath; + } + + public String getContextPath() { + return contextPath; + } + + public Cookie[] getCookies() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public long getDateHeader(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getHeader(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Enumeration getHeaderNames() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Enumeration getHeaders(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public ServletInputStream getInputStream() throws IOException { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public int getIntHeader(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Locale getLocale() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Enumeration getLocales() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getMethod() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void setParameter(String arg0, String value) { + map.put(arg0, value); + } + + public String getParameter(String arg0) { + Object result = map.get(arg0); + + if (result != null) { + return (String) map.get(arg0); + } else { + return null; + } + } + + public Map getParameterMap() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Enumeration getParameterNames() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String[] getParameterValues(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getPathInfo() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getPathTranslated() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getProtocol() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getQueryString() { + return this.queryString; + } + + public BufferedReader getReader() throws IOException { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getRealPath(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getRemoteAddr() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getRemoteHost() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getRemoteUser() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public RequestDispatcher getRequestDispatcher(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getRequestURI() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public StringBuffer getRequestURL() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getRequestedSessionId() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public boolean isRequestedSessionIdFromCookie() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public boolean isRequestedSessionIdFromURL() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public boolean isRequestedSessionIdFromUrl() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public boolean isRequestedSessionIdValid() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getScheme() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public boolean isSecure() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getServerName() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public int getServerPort() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void setServletPath(String servletPath) { + this.servletPath = servletPath; + } + + public String getServletPath() { + return this.servletPath; + } + + public HttpSession getSession(boolean arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public HttpSession getSession() { + return this.session; + } + + public boolean isUserInRole(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Principal getUserPrincipal() { + return this.principal; + } + + public void removeAttribute(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } +} diff --git a/core/src/test/java/org/acegisecurity/MockHttpServletResponse.java b/core/src/test/java/org/acegisecurity/MockHttpServletResponse.java new file mode 100644 index 0000000000..ad6010fc51 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/MockHttpServletResponse.java @@ -0,0 +1,170 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity; + +import java.io.IOException; +import java.io.PrintWriter; + +import java.util.Locale; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + + +/** + * Mocks a HttpServletResponse, recording the + * sendRedirect URL and sendError code. + * + * @author Ben Alex + * @version $Id$ + */ +public class MockHttpServletResponse implements HttpServletResponse { + //~ Instance fields ======================================================== + + private String redirect; + private int error; + + //~ Methods ================================================================ + + public void setBufferSize(int arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public int getBufferSize() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getCharacterEncoding() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public boolean isCommitted() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void setContentLength(int arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void setContentType(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void setDateHeader(String arg0, long arg1) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public int getError() { + return this.error; + } + + public void setHeader(String arg0, String arg1) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void setIntHeader(String arg0, int arg1) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void setLocale(Locale arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Locale getLocale() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public ServletOutputStream getOutputStream() throws IOException { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getRedirect() { + return redirect; + } + + public void setStatus(int arg0, String arg1) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void setStatus(int arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public PrintWriter getWriter() throws IOException { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void addCookie(Cookie arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void addDateHeader(String arg0, long arg1) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void addHeader(String arg0, String arg1) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void addIntHeader(String arg0, int arg1) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public boolean containsHeader(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String encodeRedirectURL(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String encodeRedirectUrl(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String encodeURL(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String encodeUrl(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void flushBuffer() throws IOException { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void reset() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void resetBuffer() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void sendError(int arg0, String arg1) throws IOException { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void sendError(int arg0) throws IOException { + this.error = arg0; + } + + public void sendRedirect(String arg0) throws IOException { + this.redirect = arg0; + } +} diff --git a/core/src/test/java/org/acegisecurity/MockHttpSession.java b/core/src/test/java/org/acegisecurity/MockHttpSession.java new file mode 100644 index 0000000000..8c55108ce9 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/MockHttpSession.java @@ -0,0 +1,108 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity; + +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpSessionContext; + + +/** + * Mocks a HttpSession and provides the + * getAttribute() and setAttribute() methods. + * + * @author Ben Alex + * @version $Id$ + */ +public class MockHttpSession implements HttpSession { + //~ Instance fields ======================================================== + + private Map map = new HashMap(); + + //~ Methods ================================================================ + + public void setAttribute(String arg0, Object arg1) { + map.put(arg0, arg1); + } + + public Object getAttribute(String arg0) { + return map.get(arg0); + } + + public Enumeration getAttributeNames() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public long getCreationTime() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String getId() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public long getLastAccessedTime() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void setMaxInactiveInterval(int arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public int getMaxInactiveInterval() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public boolean isNew() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public ServletContext getServletContext() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public HttpSessionContext getSessionContext() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Object getValue(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public String[] getValueNames() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void invalidate() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void putValue(String arg0, Object arg1) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void removeAttribute(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public void removeValue(String arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } +} diff --git a/core/src/test/java/org/acegisecurity/MockMethodInvocation.java b/core/src/test/java/org/acegisecurity/MockMethodInvocation.java new file mode 100644 index 0000000000..0c74e72898 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/MockMethodInvocation.java @@ -0,0 +1,52 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity; + +import org.aopalliance.intercept.MethodInvocation; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Method; + + +/** + * DOCUMENT ME! + * + * @author Ben Alex + * @version $Id$ + */ +public class MockMethodInvocation implements MethodInvocation { + //~ Methods ================================================================ + + public Object[] getArguments() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Method getMethod() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public AccessibleObject getStaticPart() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Object getThis() { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Object proceed() throws Throwable { + throw new UnsupportedOperationException("mock method not implemented"); + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/method/AbstractMethodDefinitionSourceTests.java b/core/src/test/java/org/acegisecurity/intercept/method/AbstractMethodDefinitionSourceTests.java new file mode 100644 index 0000000000..ad2f387217 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/method/AbstractMethodDefinitionSourceTests.java @@ -0,0 +1,100 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.intercept.method; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.MockMethodInvocation; + +import org.aopalliance.intercept.MethodInvocation; + + +/** + * Tests {@link AbstractMethodDefinitionSource} and associated {@link + * ConfigAttributeDefinition}. + * + * @author Ben Alex + * @version $Id$ + */ +public class AbstractMethodDefinitionSourceTests extends TestCase { + //~ Constructors =========================================================== + + public AbstractMethodDefinitionSourceTests() { + super(); + } + + public AbstractMethodDefinitionSourceTests(String arg0) { + super(arg0); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(AbstractMethodDefinitionSourceTests.class); + } + + public void testDoesNotSupportAnotherObject() { + MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, + true); + assertFalse(mds.supports(String.class)); + } + + public void testGetAttributesForANonMethodInvocation() { + MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, + true); + + try { + mds.getAttributes(new String()); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testGetAttributesForANullObject() { + MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, + true); + + try { + mds.getAttributes(null); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testGetAttributesForMethodInvocation() { + MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, + true); + + try { + mds.getAttributes(new MockMethodInvocation()); + fail("Should have thrown UnsupportedOperationException"); + } catch (UnsupportedOperationException expected) { + assertTrue(true); + } + } + + public void testSupportsMethodInvocation() { + MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false, + true); + assertTrue(mds.supports(MethodInvocation.class)); + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionAttributesTests.java b/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionAttributesTests.java new file mode 100644 index 0000000000..c436bae86b --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionAttributesTests.java @@ -0,0 +1,283 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.intercept.method; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.ConfigAttribute; +import net.sf.acegisecurity.ConfigAttributeDefinition; +import net.sf.acegisecurity.GrantedAuthority; +import net.sf.acegisecurity.GrantedAuthorityImpl; +import net.sf.acegisecurity.ITargetObject; +import net.sf.acegisecurity.MockMethodInvocation; +import net.sf.acegisecurity.OtherTargetObject; +import net.sf.acegisecurity.SecurityConfig; +import net.sf.acegisecurity.TargetObject; +import net.sf.acegisecurity.context.ContextHolder; +import net.sf.acegisecurity.context.SecureContext; +import net.sf.acegisecurity.context.SecureContextImpl; +import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; + +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import java.lang.reflect.Method; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Properties; +import java.util.Set; + + +/** + * Tests {@link MethodDefinitionAttributes}. + * + * @author Cameron Braid + * @author Ben Alex + * @version $Id$ + */ +public class MethodDefinitionAttributesTests extends TestCase { + //~ Instance fields ======================================================== + + ClassPathXmlApplicationContext applicationContext; + + //~ Constructors =========================================================== + + public MethodDefinitionAttributesTests(String a) { + super(a); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(MethodDefinitionAttributesTests.class); + } + + public void testAttributesForInterfaceTargetObject() + throws Exception { + ConfigAttributeDefinition def1 = getConfigAttributeDefinition(ITargetObject.class, + "countLength", new Class[] {String.class}); + Set set1 = toSet(def1); + assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE"))); + assertTrue(set1.contains( + new SecurityConfig("MOCK_INTERFACE_METHOD_COUNT_LENGTH"))); + + ConfigAttributeDefinition def2 = getConfigAttributeDefinition(ITargetObject.class, + "makeLowerCase", new Class[] {String.class}); + Set set2 = toSet(def2); + assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE"))); + assertTrue(set2.contains( + new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE"))); + + ConfigAttributeDefinition def3 = getConfigAttributeDefinition(ITargetObject.class, + "makeUpperCase", new Class[] {String.class}); + Set set3 = toSet(def3); + assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE"))); + assertTrue(set3.contains( + new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE"))); + } + + public void testAttributesForOtherTargetObject() throws Exception { + ConfigAttributeDefinition def1 = getConfigAttributeDefinition(OtherTargetObject.class, + "countLength", new Class[] {String.class}); + Set set1 = toSet(def1); + assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE"))); + assertTrue(set1.contains( + new SecurityConfig("MOCK_INTERFACE_METHOD_COUNT_LENGTH"))); + + // Confirm MOCK_CLASS_METHOD_COUNT_LENGTH not added, as it's a String (not a ConfigAttribute) + // Confirm also MOCK_CLASS not added, as we return null for class + assertEquals(2, set1.size()); + + ConfigAttributeDefinition def2 = getConfigAttributeDefinition(OtherTargetObject.class, + "makeLowerCase", new Class[] {String.class}); + Set set2 = toSet(def2); + assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE"))); + assertTrue(set2.contains( + new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE"))); + assertTrue(set2.contains( + new SecurityConfig("MOCK_CLASS_METHOD_MAKE_LOWER_CASE"))); + + // Confirm MOCK_CLASS not added, as we return null for class + assertEquals(3, set2.size()); + + ConfigAttributeDefinition def3 = getConfigAttributeDefinition(OtherTargetObject.class, + "makeUpperCase", new Class[] {String.class}); + Set set3 = toSet(def3); + assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE"))); + assertTrue(set3.contains( + new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE"))); + assertTrue(set3.contains(new SecurityConfig("RUN_AS"))); // defined against interface + + assertEquals(3, set3.size()); + } + + public void testAttributesForTargetObject() throws Exception { + ConfigAttributeDefinition def1 = getConfigAttributeDefinition(TargetObject.class, + "countLength", new Class[] {String.class}); + Set set1 = toSet(def1); + assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE"))); + assertTrue(set1.contains( + new SecurityConfig("MOCK_INTERFACE_METHOD_COUNT_LENGTH"))); + + assertTrue(set1.contains(new SecurityConfig("MOCK_CLASS"))); + + // Confirm the MOCK_CLASS_METHOD_COUNT_LENGTH was not added, as it's not a ConfigAttribute + assertEquals(3, set1.size()); + + ConfigAttributeDefinition def2 = getConfigAttributeDefinition(TargetObject.class, + "makeLowerCase", new Class[] {String.class}); + Set set2 = toSet(def2); + assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE"))); + assertTrue(set2.contains( + new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE"))); + assertTrue(set2.contains(new SecurityConfig("MOCK_CLASS"))); + assertTrue(set2.contains( + new SecurityConfig("MOCK_CLASS_METHOD_MAKE_LOWER_CASE"))); + assertEquals(4, set2.size()); + + ConfigAttributeDefinition def3 = getConfigAttributeDefinition(TargetObject.class, + "makeUpperCase", new Class[] {String.class}); + Set set3 = toSet(def3); + assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE"))); + assertTrue(set3.contains( + new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE"))); + assertTrue(set3.contains(new SecurityConfig("MOCK_CLASS"))); + assertTrue(set3.contains( + new SecurityConfig("MOCK_CLASS_METHOD_MAKE_UPPER_CASE"))); + assertTrue(set3.contains(new SecurityConfig("RUN_AS"))); + assertEquals(5, set3.size()); + } + + public void testMethodCallWithRunAsReplacement() throws Exception { + SecureContext context = new SecureContextImpl(); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", + "Password", + new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE")}); + context.setAuthentication(token); + ContextHolder.setContext(context); + + ITargetObject target = makeInterceptedTarget(); + String result = target.makeUpperCase("hello"); + assertEquals("HELLO net.sf.acegisecurity.MockRunAsAuthenticationToken true", + result); + + ContextHolder.setContext(null); + } + + public void testMethodCallWithoutRunAsReplacement() + throws Exception { + SecureContext context = new SecureContextImpl(); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", + "Password", + new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE")}); + context.setAuthentication(token); + ContextHolder.setContext(context); + + ITargetObject target = makeInterceptedTarget(); + String result = target.makeLowerCase("HELLO"); + + assertEquals("hello net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken true", + result); + + ContextHolder.setContext(null); + } + + private ConfigAttributeDefinition getConfigAttributeDefinition( + Class clazz, String methodName, Class[] args) throws Exception { + final Method method = clazz.getMethod(methodName, args); + MethodDefinitionAttributes source = new MethodDefinitionAttributes(); + source.setAttributes(new MockAttributes()); + + ConfigAttributeDefinition config = source.getAttributes(new MockMethodInvocation() { + public Method getMethod() { + return method; + } + }); + + return config; + } + + private ITargetObject makeInterceptedTarget() { + String PREFIX = "beans."; + DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); + Properties p = new Properties(); + p.setProperty(PREFIX + "authentication.class", + "net.sf.acegisecurity.MockAuthenticationManager"); + p.setProperty(PREFIX + "accessDecision.class", + "net.sf.acegisecurity.MockAccessDecisionManager"); + p.setProperty(PREFIX + "runAs.class", + "net.sf.acegisecurity.MockRunAsManager"); + p.setProperty(PREFIX + "attributes.class", + "net.sf.acegisecurity.intercept.method.MockAttributes"); + + p.setProperty(PREFIX + "objectDefinitionSource.class", + "net.sf.acegisecurity.intercept.method.MethodDefinitionAttributes"); + p.setProperty(PREFIX + "objectDefinitionSource.attributes(ref)", + "attributes"); + + p.setProperty(PREFIX + "securityInterceptor.class", + "net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor"); + p.setProperty(PREFIX + "securityInterceptor.authenticationManager(ref)", + "authentication"); + p.setProperty(PREFIX + "securityInterceptor.accessDecisionManager(ref)", + "accessDecision"); + p.setProperty(PREFIX + "securityInterceptor.runAsManager(ref)", "runAs"); + p.setProperty(PREFIX + + "securityInterceptor.objectDefinitionSource(ref)", + "objectDefinitionSource"); + + p.setProperty(PREFIX + "targetObject.class", + "net.sf.acegisecurity.TargetObject"); + p.setProperty(PREFIX + "target.class", + "org.springframework.aop.framework.ProxyFactoryBean"); + p.setProperty(PREFIX + "target.proxyInterfaces", + "net.sf.acegisecurity.ITargetObject"); + p.setProperty(PREFIX + "target.interceptorNames", + "securityInterceptor,targetObject"); + + (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p, + PREFIX); + + return (ITargetObject) lbf.getBean("target"); + } + + /** + * convert a ConfigAttributeDefinition into a set of + * ConfigAttribute(s) + * + * @param def the ConfigAttributeDefinition to cover + * + * @return a Set of ConfigAttributes + */ + private Set toSet(ConfigAttributeDefinition def) { + Set set = new HashSet(); + Iterator i = def.getConfigAttributes(); + + while (i.hasNext()) { + ConfigAttribute a = (ConfigAttribute) i.next(); + set.add(a); + } + + return set; + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionSourceEditorTests.java b/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionSourceEditorTests.java new file mode 100644 index 0000000000..4c950b9dc0 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionSourceEditorTests.java @@ -0,0 +1,220 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.intercept.method; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.ConfigAttributeDefinition; +import net.sf.acegisecurity.SecurityConfig; +import net.sf.acegisecurity.TargetObject; + +import org.aopalliance.intercept.MethodInvocation; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Method; + +import java.util.Iterator; + + +/** + * Tests {@link MethodDefinitionSourceEditor} and its asociated {@link + * MethodDefinitionMap}. + * + * @author Ben Alex + * @version $Id$ + */ +public class MethodDefinitionSourceEditorTests extends TestCase { + //~ Constructors =========================================================== + + public MethodDefinitionSourceEditorTests() { + super(); + } + + public MethodDefinitionSourceEditorTests(String arg0) { + super(arg0); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(MethodDefinitionSourceEditorTests.class); + } + + public void testClassNameNotFoundResultsInException() { + MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); + + try { + editor.setAsText("net.sf.acegisecurity.DOES_NOT_EXIST_NAME=FOO,BAR"); + fail("Should have given IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testClassNameNotInProperFormatResultsInException() { + MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); + + try { + editor.setAsText("DOES_NOT_EXIST_NAME=FOO,BAR"); + fail("Should have given IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testClassNameValidButMethodNameInvalidResultsInException() { + MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); + + try { + editor.setAsText( + "net.sf.acegisecurity.TargetObject.INVALID_METHOD=FOO,BAR"); + fail("Should have given IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testEmptyStringReturnsEmptyMap() { + MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); + editor.setAsText(""); + + MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); + assertEquals(0, map.getMethodMapSize()); + } + + public void testIterator() { + MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); + editor.setAsText( + "net.sf.acegisecurity.TargetObject.countLength=ROLE_ONE,ROLE_TWO,RUN_AS_ENTRY\r\nnet.sf.acegisecurity.TargetObject.make*=ROLE_NINE,ROLE_SUPERVISOR"); + + MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); + Iterator iter = map.getConfigAttributeDefinitions(); + int counter = 0; + + while (iter.hasNext()) { + iter.next(); + counter++; + } + + assertEquals(3, counter); + } + + public void testMultiMethodParsing() { + MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); + editor.setAsText( + "net.sf.acegisecurity.TargetObject.countLength=ROLE_ONE,ROLE_TWO,RUN_AS_ENTRY\r\nnet.sf.acegisecurity.TargetObject.make*=ROLE_NINE,ROLE_SUPERVISOR"); + + MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); + assertEquals(3, map.getMethodMapSize()); + } + + public void testMultiMethodParsingWhereLaterMethodsOverrideEarlierMethods() + throws Exception { + MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); + editor.setAsText( + "net.sf.acegisecurity.TargetObject.*=ROLE_GENERAL\r\nnet.sf.acegisecurity.TargetObject.makeLower*=ROLE_LOWER\r\nnet.sf.acegisecurity.TargetObject.make*=ROLE_MAKE\r\nnet.sf.acegisecurity.TargetObject.makeUpper*=ROLE_UPPER"); + + MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); + assertEquals(4, map.getMethodMapSize()); + + ConfigAttributeDefinition returnedMakeLower = map.getAttributes(new MockMethodInvocation( + TargetObject.class, "makeLowerCase", + new Class[] {String.class})); + ConfigAttributeDefinition expectedMakeLower = new ConfigAttributeDefinition(); + expectedMakeLower.addConfigAttribute(new SecurityConfig("ROLE_LOWER")); + assertEquals(expectedMakeLower, returnedMakeLower); + + ConfigAttributeDefinition returnedMakeUpper = map.getAttributes(new MockMethodInvocation( + TargetObject.class, "makeUpperCase", + new Class[] {String.class})); + ConfigAttributeDefinition expectedMakeUpper = new ConfigAttributeDefinition(); + expectedMakeUpper.addConfigAttribute(new SecurityConfig("ROLE_UPPER")); + assertEquals(expectedMakeUpper, returnedMakeUpper); + + ConfigAttributeDefinition returnedCountLength = map.getAttributes(new MockMethodInvocation( + TargetObject.class, "countLength", + new Class[] {String.class})); + ConfigAttributeDefinition expectedCountLength = new ConfigAttributeDefinition(); + expectedCountLength.addConfigAttribute(new SecurityConfig( + "ROLE_GENERAL")); + assertEquals(expectedCountLength, returnedCountLength); + } + + public void testNullReturnsEmptyMap() { + MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); + editor.setAsText(null); + + MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); + assertEquals(0, map.getMethodMapSize()); + } + + public void testSingleMethodParsing() throws Exception { + MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor(); + editor.setAsText( + "net.sf.acegisecurity.TargetObject.countLength=ROLE_ONE,ROLE_TWO,RUN_AS_ENTRY"); + + MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue(); + + ConfigAttributeDefinition returnedCountLength = map.getAttributes(new MockMethodInvocation( + TargetObject.class, "countLength", + new Class[] {String.class})); + ConfigAttributeDefinition expectedCountLength = new ConfigAttributeDefinition(); + expectedCountLength.addConfigAttribute(new SecurityConfig("ROLE_ONE")); + expectedCountLength.addConfigAttribute(new SecurityConfig("ROLE_TWO")); + expectedCountLength.addConfigAttribute(new SecurityConfig( + "RUN_AS_ENTRY")); + assertEquals(expectedCountLength, returnedCountLength); + } + + //~ Inner Classes ========================================================== + + private class MockMethodInvocation implements MethodInvocation { + Method method; + + public MockMethodInvocation(Class clazz, String methodName, + Class[] parameterTypes) throws NoSuchMethodException { + method = clazz.getMethod(methodName, parameterTypes); + } + + private MockMethodInvocation() { + super(); + } + + public Object[] getArguments() { + return null; + } + + public Method getMethod() { + return method; + } + + public AccessibleObject getStaticPart() { + return null; + } + + public Object getThis() { + return null; + } + + public Object proceed() throws Throwable { + return null; + } + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/method/MethodSecurityInterceptorTests.java b/core/src/test/java/org/acegisecurity/intercept/method/MethodSecurityInterceptorTests.java new file mode 100644 index 0000000000..79a9984f59 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/method/MethodSecurityInterceptorTests.java @@ -0,0 +1,521 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.intercept.method; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.AccessDecisionManager; +import net.sf.acegisecurity.AccessDeniedException; +import net.sf.acegisecurity.Authentication; +import net.sf.acegisecurity.AuthenticationCredentialsNotFoundException; +import net.sf.acegisecurity.ConfigAttribute; +import net.sf.acegisecurity.ConfigAttributeDefinition; +import net.sf.acegisecurity.GrantedAuthority; +import net.sf.acegisecurity.GrantedAuthorityImpl; +import net.sf.acegisecurity.ITargetObject; +import net.sf.acegisecurity.MockAccessDecisionManager; +import net.sf.acegisecurity.MockAuthenticationManager; +import net.sf.acegisecurity.MockRunAsManager; +import net.sf.acegisecurity.RunAsManager; +import net.sf.acegisecurity.context.ContextHolder; +import net.sf.acegisecurity.context.ContextImpl; +import net.sf.acegisecurity.context.SecureContext; +import net.sf.acegisecurity.context.SecureContextImpl; +import net.sf.acegisecurity.intercept.SecurityInterceptorCallback; +import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; + +import org.aopalliance.intercept.MethodInvocation; + +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader; + +import java.util.Iterator; +import java.util.Properties; + + +/** + * Tests {@link MethodSecurityInterceptor}. + * + * @author Ben Alex + * @version $Id$ + */ +public class MethodSecurityInterceptorTests extends TestCase { + //~ Constructors =========================================================== + + public MethodSecurityInterceptorTests() { + super(); + } + + public MethodSecurityInterceptorTests(String arg0) { + super(arg0); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(MethodSecurityInterceptorTests.class); + } + + public void testCallingAPublicMethodFacadeWillNotRepeatSecurityChecksWhenPassedToTheSecuredMethodItFronts() + throws Exception { + ITargetObject target = makeInterceptedTarget(); + String result = target.publicMakeLowerCase("HELLO"); + assertEquals("hello ContextHolder Not Security Aware", result); + + ContextHolder.setContext(null); + } + + public void testCallingAPublicMethodWhenPresentingASecureContextButWithoutAnyAuthenticationObject() + throws Exception { + SecureContext context = new SecureContextImpl(); + ContextHolder.setContext(context); + + ITargetObject target = makeInterceptedTarget(); + String result = target.publicMakeLowerCase("HELLO"); + assertEquals("hello Authentication empty", result); + + ContextHolder.setContext(null); + } + + public void testCallingAPublicMethodWhenPresentingAnAuthenticationObjectWillProperlySetItsIsAuthenticatedProperty() + throws Exception { + SecureContext context = new SecureContextImpl(); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", + "Password", + new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_THIS_IS_NOT_REQUIRED_AS_IT_IS_PUBLIC")}); + assertTrue(!token.isAuthenticated()); + context.setAuthentication(token); + ContextHolder.setContext(context); + + ITargetObject target = makeInterceptedTarget(); + String result = target.publicMakeLowerCase("HELLO"); + assertEquals("hello net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken false", + result); + + ContextHolder.setContext(null); + } + + public void testDeniesWhenAppropriate() throws Exception { + SecureContext context = new SecureContextImpl(); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", + "Password", + new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_NO_BENEFIT_TO_THIS_GRANTED_AUTHORITY")}); + context.setAuthentication(token); + ContextHolder.setContext(context); + + ITargetObject target = makeInterceptedTarget(); + + try { + target.makeUpperCase("HELLO"); + fail("Should have thrown AccessDeniedException"); + } catch (AccessDeniedException expected) { + assertTrue(true); + } + + ContextHolder.setContext(null); + } + + public void testGetters() { + MockAccessDecisionManager accessDecision = new MockAccessDecisionManager(); + MockRunAsManager runAs = new MockRunAsManager(); + MockAuthenticationManager authManager = new MockAuthenticationManager(); + MockMethodDefinitionSource methodSource = new MockMethodDefinitionSource(false, + true); + + MethodSecurityInterceptor si = new MethodSecurityInterceptor(); + si.setAccessDecisionManager(accessDecision); + si.setRunAsManager(runAs); + si.setAuthenticationManager(authManager); + si.setObjectDefinitionSource(methodSource); + + assertEquals(accessDecision, si.getAccessDecisionManager()); + assertEquals(runAs, si.getRunAsManager()); + assertEquals(authManager, si.getAuthenticationManager()); + assertEquals(methodSource, si.getObjectDefinitionSource()); + } + + public void testMethodCallWithRunAsReplacement() throws Exception { + SecureContext context = new SecureContextImpl(); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", + "Password", + new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_UPPER")}); + context.setAuthentication(token); + ContextHolder.setContext(context); + + ITargetObject target = makeInterceptedTarget(); + String result = target.makeUpperCase("hello"); + assertEquals("HELLO net.sf.acegisecurity.MockRunAsAuthenticationToken true", + result); + + ContextHolder.setContext(null); + } + + public void testMethodCallWithoutRunAsReplacement() + throws Exception { + SecureContext context = new SecureContextImpl(); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", + "Password", + new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_LOWER")}); + assertTrue(!token.isAuthenticated()); + context.setAuthentication(token); + ContextHolder.setContext(context); + + ITargetObject target = makeInterceptedTarget(); + String result = target.makeLowerCase("HELLO"); + + // Note we check the isAuthenticated becomes true in following line + assertEquals("hello net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken true", + result); + + ContextHolder.setContext(null); + } + + public void testRejectionOfEmptyContextHolder() throws Exception { + ITargetObject target = makeInterceptedTarget(); + + try { + target.makeUpperCase("hello"); + fail( + "Should have thrown AuthenticationCredentialsNotFoundException"); + } catch (AuthenticationCredentialsNotFoundException expected) { + assertTrue(true); + } + } + + public void testRejectionOfNonSecureContextOnContextHolder() + throws Exception { + ContextHolder.setContext(new ContextImpl()); + + ITargetObject target = makeInterceptedTarget(); + + try { + target.makeUpperCase("hello"); + fail( + "Should have thrown AuthenticationCredentialsNotFoundException"); + } catch (AuthenticationCredentialsNotFoundException expected) { + assertTrue(true); + } + + ContextHolder.setContext(null); + } + + public void testRejectionOfSecureContextThatContainsNoAuthenticationObject() + throws Exception { + ContextHolder.setContext(new SecureContextImpl()); + + ITargetObject target = makeInterceptedTarget(); + + try { + target.makeUpperCase("hello"); + fail( + "Should have thrown AuthenticationCredentialsNotFoundException"); + } catch (AuthenticationCredentialsNotFoundException expected) { + assertTrue(true); + } + + ContextHolder.setContext(null); + } + + public void testRejectsAccessDecisionManagersThatDoNotSupportMethodInvocation() { + MethodSecurityInterceptor si = new MethodSecurityInterceptor(); + si.setAccessDecisionManager(new MockAccessDecisionManagerWhichOnlySupportsStrings()); + si.setAuthenticationManager(new MockAuthenticationManager()); + si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true)); + si.setRunAsManager(new MockRunAsManager()); + + try { + si.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("AccessDecisionManager does not support MethodInvocation", + expected.getMessage()); + } + } + + public void testRejectsCallsWhenCallbackIsNull() throws Throwable { + MethodSecurityInterceptor interceptor = new MethodSecurityInterceptor(); + + try { + interceptor.interceptor(new Object(), null); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("Callback was null", expected.getMessage()); + } + } + + public void testRejectsCallsWhenObjectDefinitionSourceDoesNotSupportObject() + throws Throwable { + MethodSecurityInterceptor interceptor = new MethodSecurityInterceptor(); + interceptor.setObjectDefinitionSource(new MockObjectDefinitionSourceWhichOnlySupportsStrings()); + + try { + interceptor.interceptor(new Integer(1), + new MockSecurityInterceptorCallback()); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(expected.getMessage().startsWith("ObjectDefinitionSource does not support objects of type")); + } + } + + public void testRejectsCallsWhenObjectIsNull() throws Throwable { + MethodSecurityInterceptor interceptor = new MethodSecurityInterceptor(); + + try { + interceptor.interceptor(null, new MockSecurityInterceptorCallback()); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("Object was null", expected.getMessage()); + } + } + + public void testRejectsRunAsManagersThatDoNotSupportMethodInvocation() { + MethodSecurityInterceptor si = new MethodSecurityInterceptor(); + si.setAccessDecisionManager(new MockAccessDecisionManager()); + si.setAuthenticationManager(new MockAuthenticationManager()); + si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true)); + si.setRunAsManager(new MockRunAsManagerWhichOnlySupportsStrings()); + + try { + si.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("RunAsManager does not support MethodInvocation", + expected.getMessage()); + } + } + + public void testStartupCheckForAccessDecisionManager() { + MethodSecurityInterceptor si = new MethodSecurityInterceptor(); + si.setRunAsManager(new MockRunAsManager()); + si.setAuthenticationManager(new MockAuthenticationManager()); + + si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true)); + + try { + si.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("An AccessDecisionManager is required", + expected.getMessage()); + } + } + + public void testStartupCheckForAuthenticationManager() { + MethodSecurityInterceptor si = new MethodSecurityInterceptor(); + si.setAccessDecisionManager(new MockAccessDecisionManager()); + si.setRunAsManager(new MockRunAsManager()); + + si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true)); + + try { + si.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("An AuthenticationManager is required", + expected.getMessage()); + } + } + + public void testStartupCheckForMethodDefinitionSource() { + MethodSecurityInterceptor si = new MethodSecurityInterceptor(); + si.setAccessDecisionManager(new MockAccessDecisionManager()); + si.setRunAsManager(new MockRunAsManager()); + si.setAuthenticationManager(new MockAuthenticationManager()); + + try { + si.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("An ObjectDefinitionSource is required", + expected.getMessage()); + } + } + + public void testStartupCheckForRunAsManager() { + MethodSecurityInterceptor si = new MethodSecurityInterceptor(); + si.setAccessDecisionManager(new MockAccessDecisionManager()); + si.setAuthenticationManager(new MockAuthenticationManager()); + + si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true)); + + try { + si.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("A RunAsManager is required", expected.getMessage()); + } + } + + public void testValidationFailsIfInvalidAttributePresented() { + MethodSecurityInterceptor si = new MethodSecurityInterceptor(); + si.setAccessDecisionManager(new MockAccessDecisionManager()); + si.setRunAsManager(new MockRunAsManager()); + si.setAuthenticationManager(new MockAuthenticationManager()); + + assertTrue(si.isValidateConfigAttributes()); // check default + si.setObjectDefinitionSource(new MockMethodDefinitionSource(true, true)); + + try { + si.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("Unsupported configuration attributes: [ANOTHER_INVALID, INVALID_ATTRIBUTE]", + expected.getMessage()); + } + } + + public void testValidationNotAttemptedIfIsValidateConfigAttributesSetToFalse() { + MethodSecurityInterceptor si = new MethodSecurityInterceptor(); + si.setAccessDecisionManager(new MockAccessDecisionManager()); + si.setRunAsManager(new MockRunAsManager()); + si.setAuthenticationManager(new MockAuthenticationManager()); + + assertTrue(si.isValidateConfigAttributes()); // check default + si.setValidateConfigAttributes(false); + assertTrue(!si.isValidateConfigAttributes()); // check changed + + si.setObjectDefinitionSource(new MockMethodDefinitionSource(true, true)); + si.afterPropertiesSet(); + assertTrue(true); + } + + public void testValidationNotAttemptedIfMethodDefinitionSourceCannotReturnIterator() { + MethodSecurityInterceptor si = new MethodSecurityInterceptor(); + si.setAccessDecisionManager(new MockAccessDecisionManager()); + si.setRunAsManager(new MockRunAsManager()); + si.setAuthenticationManager(new MockAuthenticationManager()); + + assertTrue(si.isValidateConfigAttributes()); // check default + si.setObjectDefinitionSource(new MockMethodDefinitionSource(true, false)); + si.afterPropertiesSet(); + assertTrue(true); + } + + private ITargetObject makeInterceptedTarget() { + String PREFIX = "beans."; + DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); + Properties p = new Properties(); + p.setProperty(PREFIX + "authentication.class", + "net.sf.acegisecurity.MockAuthenticationManager"); + p.setProperty(PREFIX + "accessDecision.class", + "net.sf.acegisecurity.MockAccessDecisionManager"); + p.setProperty(PREFIX + "runAs.class", + "net.sf.acegisecurity.MockRunAsManager"); + + p.setProperty(PREFIX + "securityInterceptor.class", + "net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor"); + p.setProperty(PREFIX + "securityInterceptor.authenticationManager(ref)", + "authentication"); + p.setProperty(PREFIX + "securityInterceptor.accessDecisionManager(ref)", + "accessDecision"); + p.setProperty(PREFIX + "securityInterceptor.runAsManager(ref)", "runAs"); + p.setProperty(PREFIX + "securityInterceptor.objectDefinitionSource", + "net.sf.acegisecurity.ITargetObject.makeLower*=MOCK_LOWER\r\nnet.sf.acegisecurity.ITargetObject.makeUpper*=MOCK_UPPER,RUN_AS"); + + p.setProperty(PREFIX + "targetObject.class", + "net.sf.acegisecurity.TargetObject"); + p.setProperty(PREFIX + "target.class", + "org.springframework.aop.framework.ProxyFactoryBean"); + p.setProperty(PREFIX + "target.proxyInterfaces", + "net.sf.acegisecurity.ITargetObject"); + p.setProperty(PREFIX + "target.interceptorNames", + "securityInterceptor,targetObject"); + + (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p, + PREFIX); + + return (ITargetObject) lbf.getBean("target"); + } + + //~ Inner Classes ========================================================== + + private class MockAccessDecisionManagerWhichOnlySupportsStrings + implements AccessDecisionManager { + public void decide(Authentication authentication, Object object, + ConfigAttributeDefinition config) throws AccessDeniedException { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public boolean supports(Class clazz) { + if (String.class.isAssignableFrom(clazz)) { + return true; + } else { + return false; + } + } + + public boolean supports(ConfigAttribute attribute) { + return true; + } + } + + private class MockObjectDefinitionSourceWhichOnlySupportsStrings + extends AbstractMethodDefinitionSource { + public Iterator getConfigAttributeDefinitions() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public boolean supports(Class clazz) { + if (String.class.isAssignableFrom(clazz)) { + return true; + } else { + return false; + } + } + + protected ConfigAttributeDefinition lookupAttributes( + MethodInvocation mi) { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + } + + private class MockRunAsManagerWhichOnlySupportsStrings + implements RunAsManager { + public Authentication buildRunAs(Authentication authentication, + Object object, ConfigAttributeDefinition config) { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public boolean supports(Class clazz) { + if (String.class.isAssignableFrom(clazz)) { + return true; + } else { + return false; + } + } + + public boolean supports(ConfigAttribute attribute) { + return true; + } + } + + private class MockSecurityInterceptorCallback + implements SecurityInterceptorCallback { + public Object proceedWithObject(Object object) + throws Throwable { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/method/MockAttributes.java b/core/src/test/java/org/acegisecurity/intercept/method/MockAttributes.java new file mode 100644 index 0000000000..e3b3664bca --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/method/MockAttributes.java @@ -0,0 +1,160 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.intercept.method; + +import net.sf.acegisecurity.ITargetObject; +import net.sf.acegisecurity.OtherTargetObject; +import net.sf.acegisecurity.SecurityConfig; +import net.sf.acegisecurity.TargetObject; + +import org.springframework.metadata.Attributes; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + + +/** + * Used by the {@link MethodDefinitionAttributesTests}. + * + * @author Cameron Braid + * @author Ben Alex + */ +public class MockAttributes implements Attributes { + //~ Instance fields ======================================================== + + List classAttributes = Arrays.asList(new SecurityConfig[] {new SecurityConfig( + "MOCK_CLASS")}); + List classMethodAttributesCountLength = Arrays.asList(new String[] {new String( + "MOCK_CLASS_METHOD_COUNT_LENGTH")}); + List classMethodAttributesMakeLowerCase = Arrays.asList(new SecurityConfig[] {new SecurityConfig( + "MOCK_CLASS_METHOD_MAKE_LOWER_CASE")}); + List classMethodAttributesMakeUpperCase = Arrays.asList(new SecurityConfig[] {new SecurityConfig( + "MOCK_CLASS_METHOD_MAKE_UPPER_CASE")}); + List interfaceAttributes = Arrays.asList(new SecurityConfig[] {new SecurityConfig( + "MOCK_INTERFACE")}); + List interfaceMethodAttributesCountLength = Arrays.asList(new SecurityConfig[] {new SecurityConfig( + "MOCK_INTERFACE_METHOD_COUNT_LENGTH")}); + List interfaceMethodAttributesMakeLowerCase = Arrays.asList(new SecurityConfig[] {new SecurityConfig( + "MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE")}); + List interfaceMethodAttributesMakeUpperCase = Arrays.asList(new SecurityConfig[] {new SecurityConfig( + "MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE"), new SecurityConfig( + "RUN_AS")}); + + //~ Methods ================================================================ + + public Collection getAttributes(Class clazz) { + // Emphasise we return null for OtherTargetObject + if (clazz.equals(OtherTargetObject.class)) { + return null; + } + + // interface + if (clazz.equals(ITargetObject.class)) { + return interfaceAttributes; + } + + // class + if (clazz.equals(TargetObject.class)) { + return classAttributes; + } + + return null; + } + + public Collection getAttributes(Method method) { + // interface + if (method.getDeclaringClass().equals(ITargetObject.class)) { + if (method.getName().equals("countLength")) { + return interfaceMethodAttributesCountLength; + } + + if (method.getName().equals("makeLowerCase")) { + return interfaceMethodAttributesMakeLowerCase; + } + + if (method.getName().equals("makeUpperCase")) { + return interfaceMethodAttributesMakeUpperCase; + } + + if (method.getName().equals("publicMakeLowerCase")) { + throw new UnsupportedOperationException( + "mock support not implemented"); + } + } + + // class + if (method.getDeclaringClass().equals(TargetObject.class)) { + if (method.getName().equals("countLength")) { + return classMethodAttributesCountLength; + } + + if (method.getName().equals("makeLowerCase")) { + return classMethodAttributesMakeLowerCase; + } + + if (method.getName().equals("makeUpperCase")) { + return classMethodAttributesMakeUpperCase; + } + + if (method.getName().equals("publicMakeLowerCase")) { + throw new UnsupportedOperationException( + "mock support not implemented"); + } + } + + // other target object + if (method.getDeclaringClass().equals(OtherTargetObject.class)) { + if (method.getName().equals("countLength")) { + return classMethodAttributesCountLength; + } + + if (method.getName().equals("makeLowerCase")) { + return classMethodAttributesMakeLowerCase; + } + + if (method.getName().equals("makeUpperCase")) { + return null; // NB + } + + if (method.getName().equals("publicMakeLowerCase")) { + throw new UnsupportedOperationException( + "mock support not implemented"); + } + } + + return null; + } + + public Collection getAttributes(Class arg0, Class arg1) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Collection getAttributes(Field arg0, Class arg1) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Collection getAttributes(Field arg0) { + throw new UnsupportedOperationException("mock method not implemented"); + } + + public Collection getAttributes(Method arg0, Class arg1) { + throw new UnsupportedOperationException("mock method not implemented"); + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/method/MockMethodDefinitionSource.java b/core/src/test/java/org/acegisecurity/intercept/method/MockMethodDefinitionSource.java new file mode 100644 index 0000000000..52990386cd --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/method/MockMethodDefinitionSource.java @@ -0,0 +1,88 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.intercept.method; + +import net.sf.acegisecurity.ConfigAttributeDefinition; +import net.sf.acegisecurity.SecurityConfig; + +import org.aopalliance.intercept.MethodInvocation; + +import java.util.Iterator; +import java.util.List; +import java.util.Vector; + + +/** + * DOCUMENT ME! + * + * @author Ben Alex + * @version $Id$ + */ +public class MockMethodDefinitionSource extends AbstractMethodDefinitionSource { + //~ Instance fields ======================================================== + + private List list; + private boolean returnAnIterator; + + //~ Constructors =========================================================== + + public MockMethodDefinitionSource(boolean includeInvalidAttributes, + boolean returnAnIteratorWhenRequested) { + returnAnIterator = returnAnIteratorWhenRequested; + list = new Vector(); + + ConfigAttributeDefinition def1 = new ConfigAttributeDefinition(); + def1.addConfigAttribute(new SecurityConfig("MOCK_LOWER")); + list.add(def1); + + if (includeInvalidAttributes) { + ConfigAttributeDefinition def2 = new ConfigAttributeDefinition(); + def2.addConfigAttribute(new SecurityConfig("MOCK_LOWER")); + def2.addConfigAttribute(new SecurityConfig("INVALID_ATTRIBUTE")); + list.add(def2); + } + + ConfigAttributeDefinition def3 = new ConfigAttributeDefinition(); + def3.addConfigAttribute(new SecurityConfig("MOCK_UPPER")); + def3.addConfigAttribute(new SecurityConfig("RUN_AS")); + list.add(def3); + + if (includeInvalidAttributes) { + ConfigAttributeDefinition def4 = new ConfigAttributeDefinition(); + def4.addConfigAttribute(new SecurityConfig("MOCK_SOMETHING")); + def4.addConfigAttribute(new SecurityConfig("ANOTHER_INVALID")); + list.add(def4); + } + } + + private MockMethodDefinitionSource() { + super(); + } + + //~ Methods ================================================================ + + public Iterator getConfigAttributeDefinitions() { + if (returnAnIterator) { + return list.iterator(); + } else { + return null; + } + } + + protected ConfigAttributeDefinition lookupAttributes(MethodInvocation mi) { + throw new UnsupportedOperationException("mock method not implemented"); + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/web/AbstractFilterInvocationDefinitionSourceTests.java b/core/src/test/java/org/acegisecurity/intercept/web/AbstractFilterInvocationDefinitionSourceTests.java new file mode 100644 index 0000000000..c829f7b3b2 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/web/AbstractFilterInvocationDefinitionSourceTests.java @@ -0,0 +1,117 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.intercept.web; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.MockHttpServletRequest; +import net.sf.acegisecurity.MockHttpServletResponse; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + + +/** + * Tests {@link AbstractFilterInvocationDefinitionSource}. + * + * @author Ben Alex + * @version $Id$ + */ +public class AbstractFilterInvocationDefinitionSourceTests extends TestCase { + //~ Constructors =========================================================== + + public AbstractFilterInvocationDefinitionSourceTests() { + super(); + } + + public AbstractFilterInvocationDefinitionSourceTests(String arg0) { + super(arg0); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(AbstractFilterInvocationDefinitionSourceTests.class); + } + + public void testDoesNotSupportAnotherObject() { + MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false, + true); + assertFalse(mfis.supports(String.class)); + } + + public void testGetAttributesForANonFilterInvocation() { + MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false, + true); + + try { + mfis.getAttributes(new String()); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testGetAttributesForANullObject() { + MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false, + true); + + try { + mfis.getAttributes(null); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testGetAttributesForFilterInvocationSuccess() { + MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false, + true); + + try { + mfis.getAttributes(new FilterInvocation( + new MockHttpServletRequest(null, null), + new MockHttpServletResponse(), new MockFilterChain())); + fail("Should have thrown UnsupportedOperationException"); + } catch (UnsupportedOperationException expected) { + assertTrue(true); + } + } + + public void testSupportsFilterInvocation() { + MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false, + true); + assertTrue(mfis.supports(FilterInvocation.class)); + } + + //~ Inner Classes ========================================================== + + private class MockFilterChain implements FilterChain { + public void doFilter(ServletRequest arg0, ServletResponse arg1) + throws IOException, ServletException { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionMapTests.java b/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionMapTests.java new file mode 100644 index 0000000000..4d561fa140 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionMapTests.java @@ -0,0 +1,123 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.intercept.web; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.ConfigAttributeDefinition; +import net.sf.acegisecurity.MockFilterChain; +import net.sf.acegisecurity.MockHttpServletRequest; +import net.sf.acegisecurity.MockHttpServletResponse; +import net.sf.acegisecurity.SecurityConfig; + + +/** + * Tests parts of {@link FilterInvocationDefinitionMap} not tested by {@link + * FilterInvocationDefinitionSourceEditorTests}. + * + * @author Ben Alex + * @version $Id$ + */ +public class FilterInvocationDefinitionMapTests extends TestCase { + //~ Constructors =========================================================== + + public FilterInvocationDefinitionMapTests() { + super(); + } + + public FilterInvocationDefinitionMapTests(String arg0) { + super(arg0); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(FilterInvocationDefinitionMapTests.class); + } + + public void testConvertUrlToLowercaseIsFalseByDefault() { + FilterInvocationDefinitionMap map = new FilterInvocationDefinitionMap(); + assertFalse(map.isConvertUrlToLowercaseBeforeComparison()); + } + + public void testConvertUrlToLowercaseSetterRespected() { + FilterInvocationDefinitionMap map = new FilterInvocationDefinitionMap(); + map.setConvertUrlToLowercaseBeforeComparison(true); + assertTrue(map.isConvertUrlToLowercaseBeforeComparison()); + } + + public void testLookupNotRequiringExactMatchSuccessIfNotMatching() { + FilterInvocationDefinitionMap map = new FilterInvocationDefinitionMap(); + map.setConvertUrlToLowercaseBeforeComparison(true); + assertTrue(map.isConvertUrlToLowercaseBeforeComparison()); + + ConfigAttributeDefinition def = new ConfigAttributeDefinition(); + def.addConfigAttribute(new SecurityConfig("ROLE_ONE")); + map.addSecureUrl("\\A/secure/super.*\\Z", def); + + // Build a HTTP request + MockHttpServletRequest req = new MockHttpServletRequest(null); + req.setServletPath("/SeCuRE/super/somefile.html"); + + FilterInvocation fi = new FilterInvocation(req, + new MockHttpServletResponse(), new MockFilterChain()); + + ConfigAttributeDefinition response = map.lookupAttributes(fi); + assertEquals(def, response); + } + + public void testLookupRequiringExactMatchFailsIfNotMatching() { + FilterInvocationDefinitionMap map = new FilterInvocationDefinitionMap(); + assertFalse(map.isConvertUrlToLowercaseBeforeComparison()); + + ConfigAttributeDefinition def = new ConfigAttributeDefinition(); + def.addConfigAttribute(new SecurityConfig("ROLE_ONE")); + map.addSecureUrl("\\A/secure/super.*\\Z", def); + + // Build a HTTP request + MockHttpServletRequest req = new MockHttpServletRequest(null); + req.setServletPath("/SeCuRE/super/somefile.html"); + + FilterInvocation fi = new FilterInvocation(req, + new MockHttpServletResponse(), new MockFilterChain()); + + ConfigAttributeDefinition response = map.lookupAttributes(fi); + assertEquals(null, response); + } + + public void testLookupRequiringExactMatchIsSuccessful() { + FilterInvocationDefinitionMap map = new FilterInvocationDefinitionMap(); + assertFalse(map.isConvertUrlToLowercaseBeforeComparison()); + + ConfigAttributeDefinition def = new ConfigAttributeDefinition(); + def.addConfigAttribute(new SecurityConfig("ROLE_ONE")); + map.addSecureUrl("\\A/secure/super.*\\Z", def); + + // Build a HTTP request + MockHttpServletRequest req = new MockHttpServletRequest(null); + req.setServletPath("/secure/super/somefile.html"); + + FilterInvocation fi = new FilterInvocation(req, + new MockHttpServletResponse(), new MockFilterChain()); + + ConfigAttributeDefinition response = map.lookupAttributes(fi); + assertEquals(def, response); + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSourceEditorTests.java b/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSourceEditorTests.java new file mode 100644 index 0000000000..e4a4d27697 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSourceEditorTests.java @@ -0,0 +1,240 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.intercept.web; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.ConfigAttributeDefinition; +import net.sf.acegisecurity.MockFilterChain; +import net.sf.acegisecurity.MockHttpServletRequest; +import net.sf.acegisecurity.MockHttpServletResponse; +import net.sf.acegisecurity.SecurityConfig; + +import java.util.Iterator; + + +/** + * Tests {@link FilterInvocationDefinitionSourceEditor} and its associated + * {@link FilterInvocationDefinitionMap}. + * + * @author Ben Alex + * @version $Id$ + */ +public class FilterInvocationDefinitionSourceEditorTests extends TestCase { + //~ Constructors =========================================================== + + public FilterInvocationDefinitionSourceEditorTests() { + super(); + } + + public FilterInvocationDefinitionSourceEditorTests(String arg0) { + super(arg0); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(FilterInvocationDefinitionSourceEditorTests.class); + } + + public void testConvertUrlToLowercaseDefaultSettingUnchangedByEditor() { + FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); + editor.setAsText( + "\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER"); + + FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor + .getValue(); + assertFalse(map.isConvertUrlToLowercaseBeforeComparison()); + } + + public void testConvertUrlToLowercaseSettingApplied() { + FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); + editor.setAsText( + "CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON\r\n\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER"); + + FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor + .getValue(); + assertTrue(map.isConvertUrlToLowercaseBeforeComparison()); + } + + public void testEmptyStringReturnsEmptyMap() { + FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); + editor.setAsText(""); + + FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor + .getValue(); + assertEquals(0, map.getMapSize()); + } + + public void testInvalidRegularExpressionsDetected() + throws Exception { + FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); + + try { + editor.setAsText("*=SOME_ROLE"); + } catch (IllegalArgumentException expected) { + assertEquals("Malformed regular expression: *", + expected.getMessage()); + } + } + + public void testIterator() { + FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); + editor.setAsText( + "\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER"); + + FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor + .getValue(); + Iterator iter = map.getConfigAttributeDefinitions(); + int counter = 0; + + while (iter.hasNext()) { + iter.next(); + counter++; + } + + assertEquals(2, counter); + } + + public void testMapReturnsNullWhenNoMatchFound() throws Exception { + FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); + editor.setAsText("\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE"); + + FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor + .getValue(); + + MockHttpServletRequest httpRequest = new MockHttpServletRequest(null, + null); + httpRequest.setServletPath("/totally/different/path/index.html"); + + ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation( + httpRequest, new MockHttpServletResponse(), + new MockFilterChain())); + + assertEquals(null, returned); + } + + public void testMultiUrlParsing() { + FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); + editor.setAsText( + "\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER"); + + FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor + .getValue(); + assertEquals(2, map.getMapSize()); + } + + public void testNoArgsConstructor() { + try { + new FilterInvocationDefinitionMap().new EntryHolder(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testNullReturnsEmptyMap() { + FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); + editor.setAsText(null); + + FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor + .getValue(); + assertEquals(0, map.getMapSize()); + } + + public void testOrderOfEntriesIsPreservedOrderA() { + FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); + editor.setAsText( + "\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER"); + + FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor + .getValue(); + + // Test ensures we match the first entry, not the second + MockHttpServletRequest httpRequest = new MockHttpServletRequest(null, + null); + httpRequest.setServletPath("/secure/super/very_secret.html"); + + ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation( + httpRequest, new MockHttpServletResponse(), + new MockFilterChain())); + + ConfigAttributeDefinition expected = new ConfigAttributeDefinition(); + expected.addConfigAttribute(new SecurityConfig("ROLE_WE_DONT_HAVE")); + expected.addConfigAttribute(new SecurityConfig("ANOTHER_ROLE")); + + assertEquals(expected, returned); + } + + public void testOrderOfEntriesIsPreservedOrderB() { + FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); + editor.setAsText( + "\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER\r\n\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE"); + + FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor + .getValue(); + + MockHttpServletRequest httpRequest = new MockHttpServletRequest(null, + null); + httpRequest.setServletPath("/secure/super/very_secret.html"); + + ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation( + httpRequest, new MockHttpServletResponse(), + new MockFilterChain())); + + ConfigAttributeDefinition expected = new ConfigAttributeDefinition(); + expected.addConfigAttribute(new SecurityConfig("ROLE_SUPERVISOR")); + expected.addConfigAttribute(new SecurityConfig("ROLE_TELLER")); + + assertEquals(expected, returned); + } + + public void testSingleUrlParsing() throws Exception { + FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); + editor.setAsText("\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE"); + + FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor + .getValue(); + + MockHttpServletRequest httpRequest = new MockHttpServletRequest(null, + null); + httpRequest.setServletPath("/secure/super/very_secret.html"); + + ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation( + httpRequest, new MockHttpServletResponse(), + new MockFilterChain())); + + ConfigAttributeDefinition expected = new ConfigAttributeDefinition(); + expected.addConfigAttribute(new SecurityConfig("ROLE_WE_DONT_HAVE")); + expected.addConfigAttribute(new SecurityConfig("ANOTHER_ROLE")); + + assertEquals(expected, returned); + } + + public void testWhitespaceAndCommentsAndLinesWithoutEqualsSignsAreIgnored() { + FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor(); + editor.setAsText( + " \\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE \r\n \r\n \r\n // comment line \r\n \\A/testing.*\\Z=ROLE_TEST \r\n"); + + FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor + .getValue(); + assertEquals(2, map.getMapSize()); + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationTests.java b/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationTests.java new file mode 100644 index 0000000000..591945e68e --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationTests.java @@ -0,0 +1,374 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.intercept.web; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.MockFilterChain; +import net.sf.acegisecurity.MockHttpServletRequest; +import net.sf.acegisecurity.MockHttpServletResponse; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +import java.util.Enumeration; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + + +/** + * Tests {@link FilterInvocation}. + * + * @author Ben Alex + * @version $Id$ + */ +public class FilterInvocationTests extends TestCase { + //~ Constructors =========================================================== + + public FilterInvocationTests() { + super(); + } + + public FilterInvocationTests(String arg0) { + super(arg0); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(FilterInvocationTests.class); + } + + public void testGettersAndStringMethods() { + MockHttpServletRequest request = new MockHttpServletRequest(null, null); + request.setServletPath("/HelloWorld"); + + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain chain = new MockFilterChain(); + FilterInvocation fi = new FilterInvocation(request, response, chain); + assertEquals(request, fi.getRequest()); + assertEquals(request, fi.getHttpRequest()); + assertEquals(response, fi.getResponse()); + assertEquals(response, fi.getHttpResponse()); + assertEquals(chain, fi.getChain()); + assertEquals("/HelloWorld", fi.getRequestUrl()); + assertEquals("FilterInvocation: URL: /HelloWorld", fi.toString()); + } + + public void testNoArgsConstructor() { + try { + new FilterInvocation(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testRejectsNullFilterChain() { + MockHttpServletRequest request = new MockHttpServletRequest(null, null); + MockHttpServletResponse response = new MockHttpServletResponse(); + + try { + new FilterInvocation(request, response, null); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testRejectsNullServletRequest() { + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain chain = new MockFilterChain(); + + try { + new FilterInvocation(null, response, chain); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testRejectsNullServletResponse() { + MockHttpServletRequest request = new MockHttpServletRequest(null, null); + MockFilterChain chain = new MockFilterChain(); + + try { + new FilterInvocation(request, null, chain); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testRejectsServletRequestWhichIsNotHttpServletRequest() { + MockServletRequest request = new MockServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain chain = new MockFilterChain(); + + try { + new FilterInvocation(request, response, chain); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("Can only process HttpServletRequest", + expected.getMessage()); + } + } + + public void testRejectsServletResponseWhichIsNotHttpServletResponse() { + MockHttpServletRequest request = new MockHttpServletRequest(null, null); + MockServletResponse response = new MockServletResponse(); + MockFilterChain chain = new MockFilterChain(); + + try { + new FilterInvocation(request, response, chain); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("Can only process HttpServletResponse", + expected.getMessage()); + } + } + + public void testStringMethodsWithAQueryString() { + MockHttpServletRequest request = new MockHttpServletRequest("foo=bar"); + request.setServletPath("/HelloWorld"); + + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain chain = new MockFilterChain(); + FilterInvocation fi = new FilterInvocation(request, response, chain); + assertEquals("/HelloWorld?foo=bar", fi.getRequestUrl()); + assertEquals("FilterInvocation: URL: /HelloWorld?foo=bar", fi.toString()); + } + + public void testStringMethodsWithoutAnyQueryString() { + MockHttpServletRequest request = new MockHttpServletRequest(null, null); + request.setServletPath("/HelloWorld"); + + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain chain = new MockFilterChain(); + FilterInvocation fi = new FilterInvocation(request, response, chain); + assertEquals("/HelloWorld", fi.getRequestUrl()); + assertEquals("FilterInvocation: URL: /HelloWorld", fi.toString()); + } + + //~ Inner Classes ========================================================== + + private class MockServletRequest implements ServletRequest { + public void setAttribute(String arg0, Object arg1) { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public Object getAttribute(String arg0) { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public Enumeration getAttributeNames() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public void setCharacterEncoding(String arg0) + throws UnsupportedEncodingException { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public String getCharacterEncoding() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public int getContentLength() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public String getContentType() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public ServletInputStream getInputStream() throws IOException { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public Locale getLocale() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public Enumeration getLocales() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public String getParameter(String arg0) { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public Map getParameterMap() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public Enumeration getParameterNames() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public String[] getParameterValues(String arg0) { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public String getProtocol() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public BufferedReader getReader() throws IOException { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public String getRealPath(String arg0) { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public String getRemoteAddr() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public String getRemoteHost() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public RequestDispatcher getRequestDispatcher(String arg0) { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public String getScheme() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public boolean isSecure() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public String getServerName() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public int getServerPort() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public void removeAttribute(String arg0) { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + } + + private class MockServletResponse implements ServletResponse { + public void setBufferSize(int arg0) { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public int getBufferSize() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public String getCharacterEncoding() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public boolean isCommitted() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public void setContentLength(int arg0) { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public void setContentType(String arg0) { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public void setLocale(Locale arg0) { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public Locale getLocale() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public ServletOutputStream getOutputStream() throws IOException { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public PrintWriter getWriter() throws IOException { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public void flushBuffer() throws IOException { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public void reset() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + + public void resetBuffer() { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/web/FilterSecurityInterceptorTests.java b/core/src/test/java/org/acegisecurity/intercept/web/FilterSecurityInterceptorTests.java new file mode 100644 index 0000000000..420aa10a8f --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/web/FilterSecurityInterceptorTests.java @@ -0,0 +1,258 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.intercept.web; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.AccessDecisionManager; +import net.sf.acegisecurity.AccessDeniedException; +import net.sf.acegisecurity.Authentication; +import net.sf.acegisecurity.ConfigAttribute; +import net.sf.acegisecurity.ConfigAttributeDefinition; +import net.sf.acegisecurity.GrantedAuthority; +import net.sf.acegisecurity.GrantedAuthorityImpl; +import net.sf.acegisecurity.MockAccessDecisionManager; +import net.sf.acegisecurity.MockAuthenticationManager; +import net.sf.acegisecurity.MockHttpServletRequest; +import net.sf.acegisecurity.MockHttpServletResponse; +import net.sf.acegisecurity.MockHttpSession; +import net.sf.acegisecurity.MockRunAsManager; +import net.sf.acegisecurity.RunAsManager; +import net.sf.acegisecurity.SecurityConfig; +import net.sf.acegisecurity.context.ContextHolder; +import net.sf.acegisecurity.context.SecureContext; +import net.sf.acegisecurity.context.SecureContextImpl; +import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; + +import java.io.IOException; + +import java.util.Iterator; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + + +/** + * Tests {@link FiltSecurityInterceptor}. + * + * @author Ben Alex + * @version $Id$ + */ +public class FilterSecurityInterceptorTests extends TestCase { + //~ Constructors =========================================================== + + public FilterSecurityInterceptorTests() { + super(); + } + + public FilterSecurityInterceptorTests(String arg0) { + super(arg0); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(FilterSecurityInterceptorTests.class); + } + + public void testEnsuresAccessDecisionManagerSupportsFilterInvocationClass() { + FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor(); + interceptor.setAuthenticationManager(new MockAuthenticationManager()); + interceptor.setObjectDefinitionSource(new FilterInvocationDefinitionMap()); + interceptor.setRunAsManager(new MockRunAsManager()); + + interceptor.setAccessDecisionManager(new AccessDecisionManager() { + public boolean supports(Class clazz) { + return false; + } + + public boolean supports(ConfigAttribute attribute) { + return true; + } + + public void decide(Authentication authentication, + Object object, ConfigAttributeDefinition config) + throws AccessDeniedException { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + }); + + try { + interceptor.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("AccessDecisionManager does not support FilterInvocation", + expected.getMessage()); + } + } + + public void testEnsuresRunAsManagerSupportsFilterInvocationClass() { + FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor(); + interceptor.setAccessDecisionManager(new MockAccessDecisionManager()); + interceptor.setAuthenticationManager(new MockAuthenticationManager()); + interceptor.setObjectDefinitionSource(new FilterInvocationDefinitionMap()); + + interceptor.setRunAsManager(new RunAsManager() { + public boolean supports(Class clazz) { + return false; + } + + public boolean supports(ConfigAttribute attribute) { + return true; + } + + public Authentication buildRunAs( + Authentication authentication, Object object, + ConfigAttributeDefinition config) { + throw new UnsupportedOperationException( + "mock method not implemented"); + } + }); + + try { + interceptor.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("RunAsManager does not support FilterInvocation", + expected.getMessage()); + } + } + + public void testNormalStartupAndGetter() { + FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor(); + interceptor.setAccessDecisionManager(new MockAccessDecisionManager()); + interceptor.setAuthenticationManager(new MockAuthenticationManager()); + + FilterInvocationDefinitionMap fidp = new FilterInvocationDefinitionMap(); + interceptor.setObjectDefinitionSource(fidp); + interceptor.setRunAsManager(new MockRunAsManager()); + interceptor.afterPropertiesSet(); + assertTrue(true); + assertEquals(fidp, interceptor.getObjectDefinitionSource()); + } + + /** + * We just test invocation works in a success event. There is no need to + * test access denied events as the abstract parent enforces that logic, + * which is extensively tested separately. + * + * @throws Throwable DOCUMENT ME! + */ + public void testSuccessfulInvocation() throws Throwable { + // Setup the FilterSecurityInterceptor + FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor(); + interceptor.setAccessDecisionManager(new MockAccessDecisionManager()); + interceptor.setAuthenticationManager(new MockAuthenticationManager()); + interceptor.setRunAsManager(new MockRunAsManager()); + + // Setup a mock config attribute definition + ConfigAttributeDefinition def = new ConfigAttributeDefinition(); + def.addConfigAttribute(new SecurityConfig("MOCK_OK")); + + MockFilterInvocationDefinitionMap mockSource = new MockFilterInvocationDefinitionMap("/secure/page.html", + def); + interceptor.setObjectDefinitionSource(mockSource); + + // Setup our expectation that the filter chain will be invoked, as access is granted + MockFilterChain chain = new MockFilterChain(true); + + // Setup our HTTP request and response + MockHttpServletResponse response = new MockHttpServletResponse(); + MockHttpServletRequest request = new MockHttpServletRequest(null, + new MockHttpSession()); + request.setServletPath("/secure/page.html"); + + // Setup a Context + SecureContext context = new SecureContextImpl(); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", + "Password", + new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_OK")}); + context.setAuthentication(token); + ContextHolder.setContext(context); + + // Create and test our secure object + FilterInvocation fi = new FilterInvocation(request, response, chain); + interceptor.invoke(fi); + + // Destroy the Context + ContextHolder.setContext(null); + } + + //~ Inner Classes ========================================================== + + private class MockFilterChain implements FilterChain { + private boolean expectToProceed; + + public MockFilterChain(boolean expectToProceed) { + this.expectToProceed = expectToProceed; + } + + private MockFilterChain() { + super(); + } + + public void doFilter(ServletRequest request, ServletResponse response) + throws IOException, ServletException { + if (expectToProceed) { + assertTrue(true); + } else { + fail("Did not expect filter chain to proceed"); + } + } + } + + private class MockFilterInvocationDefinitionMap + implements FilterInvocationDefinitionSource { + private ConfigAttributeDefinition toReturn; + private String servletPath; + + public MockFilterInvocationDefinitionMap(String servletPath, + ConfigAttributeDefinition toReturn) { + this.servletPath = servletPath; + this.toReturn = toReturn; + } + + private MockFilterInvocationDefinitionMap() { + super(); + } + + public ConfigAttributeDefinition getAttributes(Object object) + throws IllegalArgumentException { + FilterInvocation fi = (FilterInvocation) object; + + if (servletPath.equals(fi.getHttpRequest().getServletPath())) { + return toReturn; + } else { + return null; + } + } + + public Iterator getConfigAttributeDefinitions() { + return null; + } + + public boolean supports(Class clazz) { + return true; + } + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/web/MockFilterInvocationDefinitionSource.java b/core/src/test/java/org/acegisecurity/intercept/web/MockFilterInvocationDefinitionSource.java new file mode 100644 index 0000000000..2d0372eea7 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/web/MockFilterInvocationDefinitionSource.java @@ -0,0 +1,88 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.intercept.web; + +import net.sf.acegisecurity.ConfigAttributeDefinition; +import net.sf.acegisecurity.SecurityConfig; + +import java.util.Iterator; +import java.util.List; +import java.util.Vector; + + +/** + * DOCUMENT ME! + * + * @author Ben Alex + * @version $Id$ + */ +public class MockFilterInvocationDefinitionSource + extends AbstractFilterInvocationDefinitionSource { + //~ Instance fields ======================================================== + + private List list; + private boolean returnAnIterator; + + //~ Constructors =========================================================== + + public MockFilterInvocationDefinitionSource( + boolean includeInvalidAttributes, boolean returnAnIteratorWhenRequested) { + returnAnIterator = returnAnIteratorWhenRequested; + list = new Vector(); + + ConfigAttributeDefinition def1 = new ConfigAttributeDefinition(); + def1.addConfigAttribute(new SecurityConfig("MOCK_LOWER")); + list.add(def1); + + if (includeInvalidAttributes) { + ConfigAttributeDefinition def2 = new ConfigAttributeDefinition(); + def2.addConfigAttribute(new SecurityConfig("MOCK_LOWER")); + def2.addConfigAttribute(new SecurityConfig("INVALID_ATTRIBUTE")); + list.add(def2); + } + + ConfigAttributeDefinition def3 = new ConfigAttributeDefinition(); + def3.addConfigAttribute(new SecurityConfig("MOCK_UPPER")); + def3.addConfigAttribute(new SecurityConfig("RUN_AS")); + list.add(def3); + + if (includeInvalidAttributes) { + ConfigAttributeDefinition def4 = new ConfigAttributeDefinition(); + def4.addConfigAttribute(new SecurityConfig("MOCK_SOMETHING")); + def4.addConfigAttribute(new SecurityConfig("ANOTHER_INVALID")); + list.add(def4); + } + } + + private MockFilterInvocationDefinitionSource() { + super(); + } + + //~ Methods ================================================================ + + public Iterator getConfigAttributeDefinitions() { + if (returnAnIterator) { + return list.iterator(); + } else { + return null; + } + } + + protected ConfigAttributeDefinition lookupAttributes( + FilterInvocation filterInvocation) { + throw new UnsupportedOperationException("mock method not implemented"); + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/web/SecurityEnforcementFilterTests.java b/core/src/test/java/org/acegisecurity/intercept/web/SecurityEnforcementFilterTests.java new file mode 100644 index 0000000000..a32dcd3700 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/web/SecurityEnforcementFilterTests.java @@ -0,0 +1,317 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.intercept.web; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.AccessDeniedException; +import net.sf.acegisecurity.BadCredentialsException; +import net.sf.acegisecurity.MockFilterConfig; +import net.sf.acegisecurity.MockHttpServletRequest; +import net.sf.acegisecurity.MockHttpServletResponse; +import net.sf.acegisecurity.MockHttpSession; +import net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + + +/** + * Tests {@link SecurityEnforcementFilter}. + * + * @author Ben Alex + * @version $Id$ + */ +public class SecurityEnforcementFilterTests extends TestCase { + //~ Constructors =========================================================== + + public SecurityEnforcementFilterTests() { + super(); + } + + public SecurityEnforcementFilterTests(String arg0) { + super(arg0); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(SecurityEnforcementFilterTests.class); + } + + public void testAccessDeniedWhenAccessDeniedException() + throws Exception { + // Setup our HTTP request + MockHttpServletRequest request = new MockHttpServletRequest(null, + new MockHttpSession()); + request.setServletPath("/secure/page.html"); + + // Setup our expectation that the filter chain will not be invoked, as access is denied + MockFilterChain chain = new MockFilterChain(false); + + // Setup the FilterSecurityInterceptor thrown an access denied exception + MockFilterSecurityInterceptor interceptor = new MockFilterSecurityInterceptor(true, + false); + + // Test + MockHttpServletResponse response = new MockHttpServletResponse(); + SecurityEnforcementFilter filter = new MockSecurityEnforcementFilter(interceptor, + "/login.jsp"); + filter.doFilter(request, response, chain); + assertEquals(403, response.getError()); + } + + public void testDoFilterWithNonHttpServletRequestDetected() + throws Exception { + SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); + + try { + filter.doFilter(null, new MockHttpServletResponse(), + new MockFilterChain()); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("HttpServletRequest required", expected.getMessage()); + } + } + + public void testDoFilterWithNonHttpServletResponseDetected() + throws Exception { + SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); + + try { + filter.doFilter(new MockHttpServletRequest(null, null), null, + new MockFilterChain()); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("HttpServletResponse required", expected.getMessage()); + } + } + + public void testRedirectedToLoginFormAndSessionShowsOriginalTargetWhenAuthenticationException() + throws Exception { + // Setup our HTTP request + MockHttpServletRequest request = new MockHttpServletRequest(null, + new MockHttpSession()); + request.setServletPath("/secure/page.html"); + + // Setup our expectation that the filter chain will not be invoked, as access is denied + MockFilterChain chain = new MockFilterChain(false); + + // Setup the FilterSecurityInterceptor thrown an authentication failure exceptions + MockFilterSecurityInterceptor interceptor = new MockFilterSecurityInterceptor(false, + true); + + // Test + MockHttpServletResponse response = new MockHttpServletResponse(); + SecurityEnforcementFilter filter = new MockSecurityEnforcementFilter(interceptor, + "/login.jsp"); + filter.doFilter(request, response, chain); + assertEquals("/login.jsp", response.getRedirect()); + assertEquals("/secure/page.html", + request.getSession().getAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY)); + } + + public void testStartupDetectsInvalidAppContextLocation() + throws Exception { + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("loginFormUrl", "/login.jsp"); + config.setInitParmeter("appContextLocation", + "net/sf/acegisecurity/intercept/web/securityfiltertest-invalid.xml"); + + SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("Bean context must contain at least one bean of type FilterSecurityInterceptor", + expected.getMessage()); + } + } + + public void testStartupDetectsMissingAppContextLocation() + throws Exception { + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("loginFormUrl", "/login.jsp"); + + SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("appContextLocation must be specified", + expected.getMessage()); + } + + config.setInitParmeter("appContextLocation", ""); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("appContextLocation must be specified", + expected.getMessage()); + } + } + + public void testStartupDetectsMissingInvalidAppContextLocation() + throws Exception { + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("loginFormUrl", "/login.jsp"); + config.setInitParmeter("appContextLocation", "DOES_NOT_EXIST"); + + SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertTrue(expected.getMessage().startsWith("Cannot locate")); + } + } + + public void testStartupDetectsMissingLoginFormUrl() + throws Exception { + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("appContextLocation", + "net/sf/acegisecurity/intercept/web/securityfiltertest-valid.xml"); + + SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("loginFormUrl must be specified", expected.getMessage()); + } + + config.setInitParmeter("loginFormUrl", ""); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("loginFormUrl must be specified", expected.getMessage()); + } + } + + public void testSuccessfulAccessGrant() throws Exception { + // Setup our HTTP request + MockHttpServletRequest request = new MockHttpServletRequest(null, + new MockHttpSession()); + request.setServletPath("/secure/page.html"); + + // Setup our expectation that the filter chain will be invoked, as access is granted + MockFilterChain chain = new MockFilterChain(true); + + // Setup the FilterSecurityInterceptor to not thrown any exceptions + MockFilterSecurityInterceptor interceptor = new MockFilterSecurityInterceptor(false, + false); + + // Test + MockHttpServletResponse response = new MockHttpServletResponse(); + SecurityEnforcementFilter filter = new MockSecurityEnforcementFilter(interceptor, + "/login.jsp"); + filter.doFilter(request, response, chain); + } + + public void testSuccessfulStartupAndShutdownDown() + throws Exception { + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("appContextLocation", + "net/sf/acegisecurity/intercept/web/securityfiltertest-valid.xml"); + config.setInitParmeter("loginFormUrl", "/login.jsp"); + + SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); + + filter.init(config); + filter.destroy(); + assertTrue(true); + } + + //~ Inner Classes ========================================================== + + private class MockFilterChain implements FilterChain { + private boolean expectToProceed; + + public MockFilterChain(boolean expectToProceed) { + this.expectToProceed = expectToProceed; + } + + private MockFilterChain() { + super(); + } + + public void doFilter(ServletRequest request, ServletResponse response) + throws IOException, ServletException { + if (expectToProceed) { + assertTrue(true); + } else { + fail("Did not expect filter chain to proceed"); + } + } + } + + private class MockFilterSecurityInterceptor + extends FilterSecurityInterceptor { + private boolean throwAccessDenied; + private boolean throwAuthenticationFailure; + + public MockFilterSecurityInterceptor(boolean throwAccessDenied, + boolean throwAuthenticationFailure) { + this.throwAccessDenied = throwAccessDenied; + this.throwAuthenticationFailure = throwAuthenticationFailure; + } + + private MockFilterSecurityInterceptor() { + super(); + } + + public void invoke(FilterInvocation fi) throws Throwable { + if (throwAccessDenied) { + throw new AccessDeniedException("As requested"); + } + + if (throwAuthenticationFailure) { + throw new BadCredentialsException("As requested"); + } + + fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); + } + } + + private class MockSecurityEnforcementFilter + extends SecurityEnforcementFilter { + public MockSecurityEnforcementFilter( + FilterSecurityInterceptor securityInterceptor, String loginFormUrl) { + super.securityInterceptor = securityInterceptor; + super.loginFormUrl = loginFormUrl; + } + + private MockSecurityEnforcementFilter() { + super(); + } + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-invalid.xml b/core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-invalid.xml new file mode 100644 index 0000000000..6409f0e4d0 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-invalid.xml @@ -0,0 +1,37 @@ + + + + + + + + + + marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR + dianne=emu,ROLE_TELLER + scott=wombat,ROLE_TELLER + peter=opal,disabled,ROLE_TELLER + + + + + + + diff --git a/core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-valid.xml b/core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-valid.xml new file mode 100644 index 0000000000..f80229492e --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-valid.xml @@ -0,0 +1,76 @@ + + + + + + + + + + marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR + dianne=emu,ROLE_TELLER + scott=wombat,ROLE_TELLER + peter=opal,disabled,ROLE_TELLER + + + + + + + false + true + + + + + + + + + + + + my_run_as_password + + + + + + false + + + + + + + + + + + + + + \A/secure/super.*\Z=ROLE_WE_DONT_HAVE + \A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_TELLER + + + + + diff --git a/core/src/test/java/org/acegisecurity/ui/AbstractIntegrationFilterTests.java b/core/src/test/java/org/acegisecurity/ui/AbstractIntegrationFilterTests.java new file mode 100644 index 0000000000..32451e33ed --- /dev/null +++ b/core/src/test/java/org/acegisecurity/ui/AbstractIntegrationFilterTests.java @@ -0,0 +1,262 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.ui; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.Authentication; +import net.sf.acegisecurity.GrantedAuthority; +import net.sf.acegisecurity.GrantedAuthorityImpl; +import net.sf.acegisecurity.adapters.MockPrincipal; +import net.sf.acegisecurity.adapters.PrincipalAcegiUserToken; +import net.sf.acegisecurity.context.Context; +import net.sf.acegisecurity.context.ContextHolder; +import net.sf.acegisecurity.context.SecureContext; +import net.sf.acegisecurity.context.SecureContextImpl; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + + +/** + * Tests {@link AbstractIntegrationFilter}. + * + * @author Ben Alex + * @version $Id$ + */ +public class AbstractIntegrationFilterTests extends TestCase { + //~ Constructors =========================================================== + + public AbstractIntegrationFilterTests() { + super(); + } + + public AbstractIntegrationFilterTests(String arg0) { + super(arg0); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(AbstractIntegrationFilterTests.class); + } + + public void testContextHolderContentsPreserved() throws Exception { + PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key", + "someone", "password", + new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}); + MockAbstractIntegrationFilterImpl filter = new MockAbstractIntegrationFilterImpl(principal); + MockFilterChain chain = new MockFilterChain(true, principal); + + MockSecureContextImpl secureContext = new MockSecureContextImpl( + "FOO_BAR"); + ContextHolder.setContext(secureContext); + assertEquals(secureContext, ContextHolder.getContext()); + + executeFilterInContainerSimulator(filter, null, null, chain); + + MockSecureContextImpl after = (MockSecureContextImpl) ContextHolder + .getContext(); + assertEquals(secureContext.getInfo(), after.getInfo()); + ContextHolder.setContext(null); + } + + public void testContextHolderHasAuthenticationRemoved() + throws Exception { + PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key", + "someone", "password", + new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}); + MockAbstractIntegrationFilterImpl filter = new MockAbstractIntegrationFilterImpl(principal); + MockFilterChain chain = new MockFilterChain(true, principal); + + SecureContext secureContext = new SecureContextImpl(); + secureContext.setAuthentication(principal); + ContextHolder.setContext(secureContext); + assertEquals(secureContext, ContextHolder.getContext()); + + executeFilterInContainerSimulator(filter, null, null, chain); + + SecureContext after = (SecureContext) ContextHolder.getContext(); + assertEquals(null, after.getAuthentication()); + ContextHolder.setContext(null); + } + + public void testIgnoredWhenConcreteClassReturnsANonAuthenticationObject() + throws Exception { + MockPrincipal principal = new MockPrincipal(); + MockAbstractIntegrationFilterImpl filter = new MockAbstractIntegrationFilterImpl(principal); + MockFilterChain chain = new MockFilterChain(false, null); + + Context before = ContextHolder.getContext(); + + if (before != null) { + if (before instanceof SecureContext) { + assertEquals(null, ((SecureContext) before).getAuthentication()); + } + } + + executeFilterInContainerSimulator(filter, null, null, chain); + + Context after = ContextHolder.getContext(); + + if (after != null) { + if (after instanceof SecureContext) { + assertEquals(null, ((SecureContext) after).getAuthentication()); + } + } + } + + public void testIgnoredWhenConcreteClassReturnsNullAuthenticationObject() + throws Exception { + MockAbstractIntegrationFilterImpl filter = new MockAbstractIntegrationFilterImpl(null); + MockFilterChain chain = new MockFilterChain(false, null); + + Context before = ContextHolder.getContext(); + + if (before != null) { + if (before instanceof SecureContext) { + assertEquals(null, ((SecureContext) before).getAuthentication()); + } + } + + executeFilterInContainerSimulator(filter, null, null, chain); + + Context after = ContextHolder.getContext(); + + if (after != null) { + if (after instanceof SecureContext) { + assertEquals(null, ((SecureContext) after).getAuthentication()); + } + } + } + + public void testSuccessWhenConcreteClassReturnsValidAuthenticationObject() + throws Exception { + PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key", + "someone", "password", + new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}); + MockAbstractIntegrationFilterImpl filter = new MockAbstractIntegrationFilterImpl(principal); + MockFilterChain chain = new MockFilterChain(true, principal); + + Context before = ContextHolder.getContext(); + + if (before != null) { + if (before instanceof SecureContext) { + assertEquals(null, ((SecureContext) before).getAuthentication()); + } + } + + executeFilterInContainerSimulator(filter, null, null, chain); + + Context after = ContextHolder.getContext(); + + if (after != null) { + if (after instanceof SecureContext) { + assertEquals(null, ((SecureContext) after).getAuthentication()); + } + } + } + + private void executeFilterInContainerSimulator(Filter filter, + ServletRequest request, ServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + filter.init(null); + filter.doFilter(request, response, filterChain); + filter.destroy(); + } + + //~ Inner Classes ========================================================== + + private class MockAbstractIntegrationFilterImpl + extends AbstractIntegrationFilter { + private Object extractFromContainerResult; + + public MockAbstractIntegrationFilterImpl( + Object extractFromContainerResult) { + this.extractFromContainerResult = extractFromContainerResult; + } + + private MockAbstractIntegrationFilterImpl() { + super(); + } + + public Object extractFromContainer(ServletRequest request) { + return this.extractFromContainerResult; + } + } + + private class MockFilterChain implements FilterChain { + private Authentication expectedAuthenticationObjectInContextHolder; + private boolean expectContextHolderContainSecureContext = false; + + public MockFilterChain( + boolean expectContextHolderContainSecureContext, + Authentication expectedAuthenticationObjectInContextHolder) { + if ((expectedAuthenticationObjectInContextHolder != null) + && !expectContextHolderContainSecureContext) { + throw new IllegalArgumentException( + "If an Authentication object is expected, the ContextHolder should contain a SecureContext"); + } + + this.expectContextHolderContainSecureContext = expectContextHolderContainSecureContext; + this.expectedAuthenticationObjectInContextHolder = expectedAuthenticationObjectInContextHolder; + } + + private MockFilterChain() { + super(); + } + + public void doFilter(ServletRequest request, ServletResponse response) + throws IOException, ServletException { + if (expectContextHolderContainSecureContext) { + Context context = ContextHolder.getContext(); + + if (!(context instanceof SecureContext)) { + fail("ContextHolder should have contained SecureContext"); + } + } else { + if (ContextHolder.getContext() != null) { + fail("ContextHolder should have been null but wasn't"); + } + } + } + } + + private class MockSecureContextImpl extends SecureContextImpl { + private String info; + + public MockSecureContextImpl(String info) { + this.info = info; + } + + private MockSecureContextImpl() { + super(); + } + + public String getInfo() { + return this.info; + } + } +} diff --git a/core/src/test/java/org/acegisecurity/ui/AutoIntegrationFilterTests.java b/core/src/test/java/org/acegisecurity/ui/AutoIntegrationFilterTests.java new file mode 100644 index 0000000000..a877cdaabf --- /dev/null +++ b/core/src/test/java/org/acegisecurity/ui/AutoIntegrationFilterTests.java @@ -0,0 +1,208 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.ui; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.GrantedAuthority; +import net.sf.acegisecurity.GrantedAuthorityImpl; +import net.sf.acegisecurity.MockHttpServletRequest; +import net.sf.acegisecurity.adapters.MockPrincipal; +import net.sf.acegisecurity.adapters.PrincipalAcegiUserToken; +import net.sf.acegisecurity.adapters.jboss.JbossIntegrationFilter; +import net.sf.acegisecurity.adapters.jboss.MockInitialContext; +import net.sf.acegisecurity.adapters.jboss.MockJbossIntegrationFilter; +import net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter; + +import org.jboss.security.SimplePrincipal; + +import java.security.Principal; + +import java.util.HashSet; +import java.util.Set; + +import javax.naming.Context; + +import javax.security.auth.Subject; + +import javax.servlet.ServletRequest; + + +/** + * Tests {@link AutoIntegrationFilter}. + * + * @author Ben Alex + * @version $Id$ + */ +public class AutoIntegrationFilterTests extends TestCase { + //~ Constructors =========================================================== + + public AutoIntegrationFilterTests() { + super(); + } + + public AutoIntegrationFilterTests(String arg0) { + super(arg0); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(AutoIntegrationFilterTests.class); + } + + public void testDetectsAuthenticationObjectInHttpRequest() { + AutoIntegrationFilter filter = new AutoIntegrationFilter(); + PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key", + "someone", "password", + new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}); + Object result = filter.extractFromContainer(new MockHttpServletRequest( + principal, null)); + + if (!(result instanceof PrincipalAcegiUserToken)) { + fail("Should have returned PrincipalAcegiUserToken"); + } + + PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result; + assertEquals(principal, result); + } + + public void testDetectsAuthenticationObjectInHttpSession() { + PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key", + "someone", "password", + new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}); + + AutoIntegrationFilter filter = new MockAutoIntegrationFilterHttpSession(new MockHttpSessionIntegrationFilter( + principal)); + Object result = filter.extractFromContainer(new MockHttpServletRequest( + null, null)); + + if (!(result instanceof PrincipalAcegiUserToken)) { + fail("Should have returned PrincipalAcegiUserToken"); + } + + PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result; + assertEquals(principal, result); + } + + public void testDetectsAuthenticationObjectInJboss() { + // Prepare a mock Jboss environment reflecting completed authentication + PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key", + "someone", "password", + new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}); + Context context = new MockInitialContext(makeIntoSubject(principal)); + JbossIntegrationFilter jbossFilter = new MockJbossIntegrationFilter(context); + + // Create a SimplePrincipal, which is what JBoss places into HttpRequest + SimplePrincipal simplePrincipal = new SimplePrincipal("TEST"); + + // Now try to extract authentication information via our mock AutoIntegrationFilter + AutoIntegrationFilter filter = new MockAutoIntegrationFilterJboss(jbossFilter); + Object result = filter.extractFromContainer(new MockHttpServletRequest( + simplePrincipal, null)); + + System.out.println(result); + + if (!(result instanceof PrincipalAcegiUserToken)) { + fail("Should have returned PrincipalAcegiUserToken"); + } + + PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result; + assertEquals(principal, result); + } + + public void testHandlesIfHttpRequestIsNullForSomeReason() { + AutoIntegrationFilter filter = new AutoIntegrationFilter(); + assertEquals(null, filter.extractFromContainer(null)); + } + + public void testHandlesIfThereIsNoPrincipal() { + AutoIntegrationFilter filter = new AutoIntegrationFilter(); + assertEquals(null, + filter.extractFromContainer(new MockHttpServletRequest(null, null))); + } + + public void testReturnsNullIfNonAuthenticationObjectInHttpRequest() { + AutoIntegrationFilter filter = new AutoIntegrationFilter(); + assertEquals(null, + filter.extractFromContainer( + new MockHttpServletRequest(new MockPrincipal(), null))); + } + + private Subject makeIntoSubject(Principal principal) { + Set principals = new HashSet(); + principals.add(principal); + + return new Subject(false, principals, new HashSet(), new HashSet()); + } + + //~ Inner Classes ========================================================== + + private class MockAutoIntegrationFilterHttpSession + extends AutoIntegrationFilter { + private HttpSessionIntegrationFilter filter; + + public MockAutoIntegrationFilterHttpSession( + HttpSessionIntegrationFilter filter) { + this.filter = filter; + } + + private MockAutoIntegrationFilterHttpSession() { + super(); + } + + protected HttpSessionIntegrationFilter getHttpSessionIntegrationFilter() { + return this.filter; + } + } + + private class MockAutoIntegrationFilterJboss extends AutoIntegrationFilter { + private JbossIntegrationFilter filter; + + public MockAutoIntegrationFilterJboss(JbossIntegrationFilter filter) { + this.filter = filter; + } + + private MockAutoIntegrationFilterJboss() { + super(); + } + + protected JbossIntegrationFilter getJbossIntegrationFilter() { + return this.filter; + } + } + + private class MockHttpSessionIntegrationFilter + extends HttpSessionIntegrationFilter { + private Object toReturn; + + public MockHttpSessionIntegrationFilter(Object toReturn) { + this.toReturn = toReturn; + } + + private MockHttpSessionIntegrationFilter() { + super(); + } + + public Object extractFromContainer(ServletRequest request) { + return this.toReturn; + } + } +} diff --git a/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java b/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java new file mode 100644 index 0000000000..9b024cce48 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java @@ -0,0 +1,495 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.ui.webapp; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.Authentication; +import net.sf.acegisecurity.MockFilterConfig; +import net.sf.acegisecurity.MockHttpServletRequest; +import net.sf.acegisecurity.MockHttpServletResponse; +import net.sf.acegisecurity.MockHttpSession; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + + +/** + * Tests {@link AuthenticationProcessingFilter}. + * + * @author Ben Alex + * @version $Id$ + */ +public class AuthenticationProcessingFilterTests extends TestCase { + //~ Constructors =========================================================== + + public AuthenticationProcessingFilterTests() { + super(); + } + + public AuthenticationProcessingFilterTests(String arg0) { + super(arg0); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(AuthenticationProcessingFilterTests.class); + } + + public void testDoFilterWithNonHttpServletRequestDetected() + throws Exception { + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + + try { + filter.doFilter(null, new MockHttpServletResponse(), + new MockFilterChain()); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("Can only process HttpServletRequest", + expected.getMessage()); + } + } + + public void testDoFilterWithNonHttpServletResponseDetected() + throws Exception { + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + + try { + filter.doFilter(new MockHttpServletRequest(null, null), null, + new MockFilterChain()); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("Can only process HttpServletResponse", + expected.getMessage()); + } + } + + public void testFailedAuthenticationRedirectsAppropriately() + throws Exception { + // Setup our HTTP request + MockHttpServletRequest request = new MockHttpServletRequest(null, + new MockHttpSession()); + request.setContextPath("/myApp"); + request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_USERNAME_KEY, + "marissa"); + request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_PASSWORD_KEY, + "WRONG_PASSWORD"); + request.setServletPath("/j_acegi_security_check"); + + // Setup our filter configuration + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("appContextLocation", + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + config.setInitParmeter("defaultTargetUrl", "/"); + config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); + + // Setup our expectation that the filter chain will not be invoked, as we redirect to authenticationFailureUrl + MockFilterChain chain = new MockFilterChain(false); + MockHttpServletResponse response = new MockHttpServletResponse(); + + // Test + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + executeFilterInContainerSimulator(config, filter, request, response, + chain); + System.out.println(response.getRedirect()); + assertEquals("/myApp/failed.jsp", response.getRedirect()); + assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) == null); + } + + public void testFilterProcessesUrlVariationsRespected() + throws Exception { + // Setup our HTTP request + MockHttpServletRequest request = new MockHttpServletRequest(null, + new MockHttpSession()); + request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_USERNAME_KEY, + "marissa"); + request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_PASSWORD_KEY, + "koala"); + request.setServletPath("/j_my_security_check"); + + // Setup our filter configuration + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("appContextLocation", + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + config.setInitParmeter("defaultTargetUrl", "/"); + config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); + config.setInitParmeter("filterProcessesUrl", "/j_my_security_check"); + + // Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl + MockFilterChain chain = new MockFilterChain(false); + MockHttpServletResponse response = new MockHttpServletResponse(); + + // Test + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + executeFilterInContainerSimulator(config, filter, request, response, + chain); + assertEquals("/", response.getRedirect()); + assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) != null); + assertEquals("marissa", + ((Authentication) request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY)).getPrincipal() + .toString()); + } + + public void testIgnoresAnyServletPathOtherThanFilterProcessesUrl() + throws Exception { + // Setup our HTTP request + MockHttpServletRequest request = new MockHttpServletRequest(null, + new MockHttpSession()); + request.setServletPath("/j_some_other_url"); + + // Setup our filter configuration + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("appContextLocation", + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + config.setInitParmeter("defaultTargetUrl", "/"); + config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); + + // Setup our expectation that the filter chain will be invoked, as should just proceed with chain + MockFilterChain chain = new MockFilterChain(true); + + // Test + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + executeFilterInContainerSimulator(config, filter, request, + new MockHttpServletResponse(), chain); + } + + public void testNormalOperationWithDefaultFilterProcessesUrl() + throws Exception { + // Setup our HTTP request + MockHttpServletRequest request = new MockHttpServletRequest(null, + new MockHttpSession()); + request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_USERNAME_KEY, + "marissa"); + request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_PASSWORD_KEY, + "koala"); + request.setServletPath("/j_acegi_security_check"); + + // Setup our filter configuration + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("appContextLocation", + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + config.setInitParmeter("defaultTargetUrl", "/"); + config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); + + // Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl + MockFilterChain chain = new MockFilterChain(false); + MockHttpServletResponse response = new MockHttpServletResponse(); + + // Test + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + executeFilterInContainerSimulator(config, filter, request, response, + chain); + assertEquals("/", response.getRedirect()); + assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) != null); + assertEquals("marissa", + ((Authentication) request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY)).getPrincipal() + .toString()); + } + + public void testNullPasswordHandledGracefully() throws Exception { + // Setup our HTTP request + MockHttpServletRequest request = new MockHttpServletRequest(null, + new MockHttpSession()); + request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_USERNAME_KEY, + "marissa"); + request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_PASSWORD_KEY, + null); + request.setServletPath("/j_acegi_security_check"); + + // Setup our filter configuration + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("appContextLocation", + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + config.setInitParmeter("defaultTargetUrl", "/"); + config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); + + // Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl + MockFilterChain chain = new MockFilterChain(false); + MockHttpServletResponse response = new MockHttpServletResponse(); + + // Test + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + executeFilterInContainerSimulator(config, filter, request, response, + chain); + assertEquals("/failed.jsp", response.getRedirect()); + assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) == null); + } + + public void testNullUsernameHandledGracefully() throws Exception { + // Setup our HTTP request + MockHttpServletRequest request = new MockHttpServletRequest(null, + new MockHttpSession()); + request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_USERNAME_KEY, + null); + request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_PASSWORD_KEY, + "koala"); + request.setServletPath("/j_acegi_security_check"); + + // Setup our filter configuration + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("appContextLocation", + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + config.setInitParmeter("defaultTargetUrl", "/"); + config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); + + // Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl + MockFilterChain chain = new MockFilterChain(false); + MockHttpServletResponse response = new MockHttpServletResponse(); + + // Test + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + executeFilterInContainerSimulator(config, filter, request, response, + chain); + assertEquals("/failed.jsp", response.getRedirect()); + assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) == null); + } + + public void testStartupDetectsInvalidAppContextLocation() + throws Exception { + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("defaultTargetUrl", "/"); + config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); + config.setInitParmeter("appContextLocation", + "net/sf/acegisecurity/ui/webapp/filtertest-invalid.xml"); + + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("Bean context must contain at least one bean of type AuthenticationManager", + expected.getMessage()); + } + } + + public void testStartupDetectsMissingAppContextLocation() + throws Exception { + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("defaultTargetUrl", "/"); + config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); + + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("appContextLocation must be specified", + expected.getMessage()); + } + + config.setInitParmeter("appContextLocation", ""); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("appContextLocation must be specified", + expected.getMessage()); + } + } + + public void testStartupDetectsMissingAuthenticationFailureUrl() + throws Exception { + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("appContextLocation", + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + config.setInitParmeter("defaultTargetUrl", "/"); + + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("authenticationFailureUrl must be specified", + expected.getMessage()); + } + + config.setInitParmeter("authenticationFailureUrl", ""); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("authenticationFailureUrl must be specified", + expected.getMessage()); + } + } + + public void testStartupDetectsMissingDefaultTargetUrl() + throws Exception { + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); + config.setInitParmeter("appContextLocation", + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("defaultTargetUrl must be specified", + expected.getMessage()); + } + + config.setInitParmeter("defaultTargetUrl", ""); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("defaultTargetUrl must be specified", + expected.getMessage()); + } + } + + public void testStartupDetectsMissingInvalidAppContextLocation() + throws Exception { + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("defaultTargetUrl", "/"); + config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); + config.setInitParmeter("appContextLocation", "DOES_NOT_EXIST"); + + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertTrue(expected.getMessage().startsWith("Cannot locate")); + } + } + + public void testSuccessLoginThenFailureLoginResultsInSessionLoosingToken() + throws Exception { + // Setup our HTTP request + MockHttpServletRequest request = new MockHttpServletRequest(null, + new MockHttpSession()); + request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_USERNAME_KEY, + "marissa"); + request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_PASSWORD_KEY, + "koala"); + request.setServletPath("/j_acegi_security_check"); + + // Setup our filter configuration + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("appContextLocation", + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + config.setInitParmeter("defaultTargetUrl", "/"); + config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); + + // Setup our expectation that the filter chain will not be invoked, as we redirect to authenticationFailureUrl + MockFilterChain chain = new MockFilterChain(false); + MockHttpServletResponse response = new MockHttpServletResponse(); + + // Test + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + executeFilterInContainerSimulator(config, filter, request, response, + chain); + assertEquals("/", response.getRedirect()); + assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) != null); + + // Now try again with a wrong password + MockHttpServletRequest request2 = new MockHttpServletRequest(null, + new MockHttpSession()); + request2.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_USERNAME_KEY, + "marissa"); + request2.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_PASSWORD_KEY, + "WRONG_PASSWORD"); + request2.setServletPath("/j_acegi_security_check"); + + executeFilterInContainerSimulator(config, filter, request2, response, + chain); + assertTrue(request2.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) == null); + } + + public void testSuccessfulAuthenticationCausesRedirectToSessionSpecifiedUrl() + throws Exception { + // Setup our HTTP request + MockHttpServletRequest request = new MockHttpServletRequest(null, + new MockHttpSession()); + request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_USERNAME_KEY, + "marissa"); + request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_PASSWORD_KEY, + "koala"); + request.setServletPath("/j_acegi_security_check"); + request.getSession().setAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY, + "/my-destination"); + + // Setup our filter configuration + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("appContextLocation", + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + config.setInitParmeter("defaultTargetUrl", "/"); + config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); + + // Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl + MockFilterChain chain = new MockFilterChain(false); + MockHttpServletResponse response = new MockHttpServletResponse(); + + // Test + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + executeFilterInContainerSimulator(config, filter, request, response, + chain); + assertEquals("/my-destination", response.getRedirect()); + assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) != null); + } + + private void executeFilterInContainerSimulator(FilterConfig filterConfig, + Filter filter, ServletRequest request, ServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + filter.init(filterConfig); + filter.doFilter(request, response, filterChain); + filter.destroy(); + } + + //~ Inner Classes ========================================================== + + private class MockFilterChain implements FilterChain { + private boolean expectToProceed; + + public MockFilterChain(boolean expectToProceed) { + this.expectToProceed = expectToProceed; + } + + private MockFilterChain() { + super(); + } + + public void doFilter(ServletRequest request, ServletResponse response) + throws IOException, ServletException { + if (expectToProceed) { + assertTrue(true); + } else { + fail("Did not expect filter chain to proceed"); + } + } + } +} diff --git a/core/src/test/java/org/acegisecurity/ui/webapp/HttpSessionIntegrationFilterTests.java b/core/src/test/java/org/acegisecurity/ui/webapp/HttpSessionIntegrationFilterTests.java new file mode 100644 index 0000000000..53d7c6309b --- /dev/null +++ b/core/src/test/java/org/acegisecurity/ui/webapp/HttpSessionIntegrationFilterTests.java @@ -0,0 +1,93 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.ui.webapp; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.GrantedAuthority; +import net.sf.acegisecurity.GrantedAuthorityImpl; +import net.sf.acegisecurity.MockHttpServletRequest; +import net.sf.acegisecurity.MockHttpSession; +import net.sf.acegisecurity.adapters.PrincipalAcegiUserToken; + + +/** + * Tests {@link HttpSessionIntegrationFilter}. + * + * @author Ben Alex + * @version $Id$ + */ +public class HttpSessionIntegrationFilterTests extends TestCase { + //~ Constructors =========================================================== + + public HttpSessionIntegrationFilterTests() { + super(); + } + + public HttpSessionIntegrationFilterTests(String arg0) { + super(arg0); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(HttpSessionIntegrationFilterTests.class); + } + + public void testCorrectOperation() { + // Build a mock session containing the authenticated user + PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key", + "someone", "password", + new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}); + MockHttpSession session = new MockHttpSession(); + session.setAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY, + principal); + + // Confirm filter can extract required credentials from session + HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter(); + Object result = filter.extractFromContainer(new MockHttpServletRequest( + null, session)); + + if (!(result instanceof PrincipalAcegiUserToken)) { + fail("Should have returned PrincipalAcegiUserToken"); + } + + PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result; + assertEquals(principal, result); + } + + public void testHandlesIfHttpRequestIsNullForSomeReason() { + HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter(); + assertEquals(null, filter.extractFromContainer(null)); + } + + public void testHandlesIfHttpSessionIsNullForSomeReason() { + HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter(); + assertEquals(null, + filter.extractFromContainer(new MockHttpServletRequest(null, null))); + } + + public void testHandlesIfThereIsNoPrincipalInTheHttpSession() { + HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter(); + assertEquals(null, + filter.extractFromContainer( + new MockHttpServletRequest(null, new MockHttpSession()))); + } +} diff --git a/core/src/test/java/org/acegisecurity/ui/webapp/filtertest-invalid.xml b/core/src/test/java/org/acegisecurity/ui/webapp/filtertest-invalid.xml new file mode 100644 index 0000000000..d2d53302fa --- /dev/null +++ b/core/src/test/java/org/acegisecurity/ui/webapp/filtertest-invalid.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR + dianne=emu,ROLE_TELLER + scott=wombat,ROLE_TELLER + peter=opal,disabled,ROLE_TELLER + + + + + + + diff --git a/core/src/test/java/org/acegisecurity/ui/webapp/filtertest-valid.xml b/core/src/test/java/org/acegisecurity/ui/webapp/filtertest-valid.xml new file mode 100644 index 0000000000..df0c6150ca --- /dev/null +++ b/core/src/test/java/org/acegisecurity/ui/webapp/filtertest-valid.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR + dianne=emu,ROLE_TELLER + scott=wombat,ROLE_TELLER + peter=opal,disabled,ROLE_TELLER + + + + + + + + false + true + + + + + + + + + + + +