2
0
Ben Alex 21 жил өмнө
parent
commit
862f45e02f

+ 270 - 0
integration-test/src/net/sf/acegisecurity/integrationtests/web/AbstractContactsTests.java

@@ -0,0 +1,270 @@
+/* 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.integrationtests.web;
+
+import com.meterware.httpunit.GetMethodWebRequest;
+import com.meterware.httpunit.WebConversation;
+import com.meterware.httpunit.WebForm;
+import com.meterware.httpunit.WebLink;
+import com.meterware.httpunit.WebRequest;
+import com.meterware.httpunit.WebResponse;
+
+import junit.framework.TestCase;
+
+import java.net.URL;
+
+
+/**
+ * Tests the Contacts sample application from a HTTP user's perspective.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public abstract class AbstractContactsTests extends TestCase {
+    //~ Methods ================================================================
+
+    /**
+     * Returns the base URL where the Contacts application can be found, such
+     * as <code>http://localhost:8080/contacts</code>. There should be no
+     * ending slash.
+     *
+     * @return DOCUMENT ME!
+     */
+    public abstract String getBaseUrl();
+
+    public final void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(AbstractContactsTests.class);
+    }
+
+    public void testHelloPageAccessible() throws Exception {
+        WebConversation conversation = new WebConversation();
+        WebRequest request = new GetMethodWebRequest(getBaseUrl());
+
+        WebResponse response = conversation.getResponse(request);
+        assertEquals("Contacts Security Demo", response.getTitle());
+        assertEquals(2, response.getLinks().length); // debug and manage links
+        assertTrue(response.getText().lastIndexOf("sample.contact.Contact@") != -1);
+    }
+
+    public void testLoginNameCaseSensitive() throws Exception {
+        WebConversation conversation = new WebConversation();
+        WebRequest request = new GetMethodWebRequest(getBaseUrl());
+
+        WebResponse helloPage = conversation.getResponse(request);
+        WebLink debugLink = helloPage.getLinkWith("Debug");
+        WebResponse loginPage = debugLink.click();
+        assertEquals(1, loginPage.getForms()[0].getSubmitButtons().length);
+
+        WebForm loginForm = loginPage.getForms()[0];
+        loginPage = null;
+
+        loginForm.setParameter("j_username", "mArIsSA");
+        loginForm.setParameter("j_password", "koala");
+
+        WebResponse loginOutcome = conversation.getResponse(loginForm
+                .getRequest("submit"));
+
+        assertTrue(loginOutcome.getText().lastIndexOf("SUCCESS!") != -1);
+    }
+
+    public void testLoginPasswordCaseSensitive() throws Exception {
+        WebConversation conversation = new WebConversation();
+        WebRequest request = new GetMethodWebRequest(getBaseUrl());
+
+        WebResponse helloPage = conversation.getResponse(request);
+        WebLink debugLink = helloPage.getLinkWith("Debug");
+        WebResponse loginPage = debugLink.click();
+        assertEquals(1, loginPage.getForms()[0].getSubmitButtons().length);
+
+        WebForm loginForm = loginPage.getForms()[0];
+        loginPage = null;
+
+        loginForm.setParameter("j_username", "dianne");
+        loginForm.setParameter("j_password", "EmU");
+
+        WebResponse loginOutcome = conversation.getResponse(loginForm
+                .getRequest("submit"));
+
+        assertEquals("Login", loginOutcome.getTitle());
+    }
+
+    public void testLoginSuccess() throws Exception {
+        WebConversation conversation = new WebConversation();
+        WebRequest request = new GetMethodWebRequest(getBaseUrl());
+
+        WebResponse helloPage = conversation.getResponse(request);
+        WebLink debugLink = helloPage.getLinkWith("Debug");
+        WebResponse loginPage = debugLink.click();
+        assertEquals(1, loginPage.getForms()[0].getSubmitButtons().length);
+
+        WebForm loginForm = loginPage.getForms()[0];
+        loginPage = null;
+
+        loginForm.setParameter("j_username", "marissa");
+        loginForm.setParameter("j_password", "koala");
+
+        WebResponse loginOutcome = conversation.getResponse(loginForm
+                .getRequest("submit"));
+
+        assertTrue(loginOutcome.getText().lastIndexOf("SUCCESS!") != -1);
+    }
+
+    public void testLoginUnknownUsername() throws Exception {
+        WebConversation conversation = new WebConversation();
+        WebRequest request = new GetMethodWebRequest(getBaseUrl());
+
+        WebResponse helloPage = conversation.getResponse(request);
+        WebLink debugLink = helloPage.getLinkWith("Debug");
+        WebResponse loginPage = debugLink.click();
+        assertEquals(1, loginPage.getForms()[0].getSubmitButtons().length);
+
+        WebForm loginForm = loginPage.getForms()[0];
+        loginPage = null;
+
+        loginForm.setParameter("j_username", "angella");
+        loginForm.setParameter("j_password", "echidna");
+
+        WebResponse loginOutcome = conversation.getResponse(loginForm
+                .getRequest("submit"));
+
+        assertEquals("Login", loginOutcome.getTitle());
+    }
+
+    public void testSessionAsMarissa() throws Exception {
+        WebConversation conversation = new WebConversation();
+        WebRequest request = new GetMethodWebRequest(getBaseUrl());
+
+        WebResponse helloPage = conversation.getResponse(request);
+        WebLink manageLink = helloPage.getLinkWith("Manage");
+        WebResponse loginPage = manageLink.click();
+        manageLink = null;
+        assertEquals(1, loginPage.getForms()[0].getSubmitButtons().length);
+
+        WebForm loginForm = loginPage.getForms()[0];
+        loginPage = null;
+
+        loginForm.setParameter("j_username", "marissa");
+        loginForm.setParameter("j_password", "koala");
+
+        WebResponse loginOutcome = conversation.getResponse(loginForm
+                .getRequest("submit"));
+
+        assertEquals("Your Contacts", loginOutcome.getTitle());
+        assertTrue(loginOutcome.getText().lastIndexOf("marissa's Contacts") != -1);
+        assertEquals(4, loginOutcome.getTables()[0].getRowCount()); // 3 contacts + header
+        assertEquals(5, loginOutcome.getLinks().length); // 3 contacts + add + logoff
+
+        WebLink addLink = loginOutcome.getLinkWith("Add");
+        loginOutcome = null;
+
+        WebResponse addPage = addLink.click();
+        WebForm addForm = addPage.getForms()[0];
+        addPage = null;
+
+        addForm.setParameter("name", "");
+        addForm.setParameter("email", "");
+
+        WebResponse addOutcomeFail = conversation.getResponse(addForm
+                .getRequest("execute"));
+
+        assertEquals(new URL(getBaseUrl() + "/secure/add.htm"),
+            addOutcomeFail.getURL());
+        assertTrue(addOutcomeFail.getText().lastIndexOf("Please fix all errors!") != -1);
+        addOutcomeFail = null;
+
+        addForm.setParameter("name", "somebody");
+        addForm.setParameter("email", "them@somewhere.com");
+
+        WebResponse addOutcomeSuccess = conversation.getResponse(addForm
+                .getRequest("execute"));
+
+        assertEquals("Your Contacts", addOutcomeSuccess.getTitle());
+        assertTrue(addOutcomeSuccess.getText().lastIndexOf("marissa's Contacts") != -1);
+        assertEquals(5, addOutcomeSuccess.getTables()[0].getRowCount()); // 4 contacts + header
+        assertEquals(6, addOutcomeSuccess.getLinks().length); // 4 contacts + add + logoff
+
+        WebLink logout = addOutcomeSuccess.getLinkWith("Logoff");
+        addOutcomeSuccess = null;
+
+        WebResponse loggedOut = logout.click();
+        assertEquals("Contacts Security Demo", loggedOut.getTitle());
+
+        WebLink debugLink = loggedOut.getLinkWith("Debug");
+        loggedOut = null;
+
+        WebResponse loginAgainPage = debugLink.click();
+        assertEquals("Login", loginAgainPage.getTitle());
+    }
+
+    public void testSessionAsScott() throws Exception {
+        WebConversation conversation = new WebConversation();
+        WebRequest request = new GetMethodWebRequest(getBaseUrl());
+
+        WebResponse helloPage = conversation.getResponse(request);
+        WebLink manageLink = helloPage.getLinkWith("Manage");
+        WebResponse loginPage = manageLink.click();
+        manageLink = null;
+        assertEquals(1, loginPage.getForms()[0].getSubmitButtons().length);
+
+        WebForm loginForm = loginPage.getForms()[0];
+        loginPage = null;
+
+        loginForm.setParameter("j_username", "scott");
+        loginForm.setParameter("j_password", "wombat");
+
+        WebResponse loginOutcome = conversation.getResponse(loginForm
+                .getRequest("submit"));
+
+        assertEquals("Your Contacts", loginOutcome.getTitle());
+        assertTrue(loginOutcome.getText().lastIndexOf("scott's Contacts") != -1);
+        assertEquals(3, loginOutcome.getTables()[0].getRowCount()); // 2 contacts + header
+        assertEquals(2, loginOutcome.getLinks().length); // add + logoff only
+
+        WebLink addLink = loginOutcome.getLinkWith("Add");
+        loginOutcome = null;
+
+        WebResponse addPage = addLink.click();
+        WebForm addForm = addPage.getForms()[0];
+        addPage = null;
+
+        addForm.setParameter("name", "somebody");
+        addForm.setParameter("email", "them@somewhere.com");
+
+        WebResponse addOutcomeSuccess = conversation.getResponse(addForm
+                .getRequest("execute"));
+
+        assertEquals("Your Contacts", addOutcomeSuccess.getTitle());
+        assertTrue(addOutcomeSuccess.getText().lastIndexOf("scott's Contacts") != -1);
+        assertEquals(4, addOutcomeSuccess.getTables()[0].getRowCount()); // 3 contacts + header
+        assertEquals(2, addOutcomeSuccess.getLinks().length); // add + logoff only
+
+        WebLink logout = addOutcomeSuccess.getLinkWith("Logoff");
+        addOutcomeSuccess = null;
+
+        WebResponse loggedOut = logout.click();
+        assertEquals("Contacts Security Demo", loggedOut.getTitle());
+
+        WebLink debugLink = loggedOut.getLinkWith("Debug");
+        loggedOut = null;
+
+        WebResponse loginAgainPage = debugLink.click();
+        assertEquals("Login", loginAgainPage.getTitle());
+    }
+}

+ 31 - 0
integration-test/src/net/sf/acegisecurity/integrationtests/web/ContainerAdapterContactsTests.java

@@ -0,0 +1,31 @@
+/* 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.integrationtests.web;
+
+/**
+ * Returns information required to run container adapters version of Contacts
+ * application test.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class ContainerAdapterContactsTests extends AbstractContactsTests {
+    //~ Methods ================================================================
+
+    public String getBaseUrl() {
+        return "http://localhost:8080/contacts-container-adapter";
+    }
+}

+ 31 - 0
integration-test/src/net/sf/acegisecurity/integrationtests/web/FilterContactsTests.java

@@ -0,0 +1,31 @@
+/* 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.integrationtests.web;
+
+/**
+ * Returns information required to run filters version of Contacts application
+ * test.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class FilterContactsTests extends AbstractContactsTests {
+    //~ Methods ================================================================
+
+    public String getBaseUrl() {
+        return "http://localhost:8080/contacts";
+    }
+}

+ 7 - 0
samples/contacts/etc/ca/jboss-web.xml

@@ -0,0 +1,7 @@
+<!--
+  - $Id$
+  - File will be copied into WAR's WEB-INF directory if using container adapter
+  -->
+<jboss-web>
+    <security-domain>java:/jaas/SpringPoweredRealm</security-domain>
+</jboss-web>

+ 43 - 0
samples/contacts/etc/ca/login.jsp

@@ -0,0 +1,43 @@
+<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %>
+<%-- This page will be copied into WAR's root directory if using container adapter --%>
+<html>
+  <head>
+    <title>Login</title>
+  </head>
+
+  <body>
+    <h1>Login</h1>
+
+	<P>If you've used the standard springsecurity.xml, try these users:
+	<P>
+	<P>username <b>marissa</b>, password <b>koala</b> (granted ROLE_SUPERVISOR)
+	<P>username <b>dianne</b>, password <b>emu</b> (not a supervisor)
+	<p>username <b>scott</b>, password <b>wombat</b> (not a supervisor)
+	<p>
+	
+    <%-- this form-login-page form is also used as the 
+         form-error-page to ask for a login again.
+         --%>
+    <c:if test="${not empty param.login_error}">
+      <font color="red">
+        Your login attempt was not successful, try again.
+      </font>
+    </c:if>
+
+    <form action="<c:url value='j_security_check'/>" method="POST">
+      <table>
+        <tr><td>User:</td><td><input type='text' name='j_username'></td></tr>
+        <tr><td>Password:</td><td><input type='password' name='j_password'></td></tr>
+
+        <tr><td colspan='2'><input name="submit" type="submit"></td></tr>
+        <tr><td colspan='2'><input name="reset" type="reset"></td></tr>
+      </table>
+
+      <!--
+        -  The j_uri is a Resin requirement (ignored by other containers)
+        -->
+      <input type='hidden' name='j_uri' value='/secure/index.htm'/>
+    </form>
+
+  </body>
+</html>

+ 49 - 0
samples/contacts/etc/ca/resin-acegisecurity.xml

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+<!--
+ * The Acegi Security System for Spring is published under the terms
+ * of the Apache Software License.
+ *
+ * This springsecurity.xml file will only be used by Resin. Normally the
+ * springsecurity.xml is container-wide, but in the case of Resin it is
+ * web application specific.
+ *
+ * $Id$
+ *
+ * This file will be copied into WAR's classes directory if using container adapter
+ *
+-->
+
+<beans>
+
+	<!-- ================= CONTAINER ADAPTER CONFIGURATION ================ -->
+	
+	<!-- Data access object which stores authentication information -->
+	<bean id="inMemoryDaoImpl" class="net.sf.acegisecurity.providers.dao.memory.InMemoryDaoImpl">
+  		<property name="userMap">
+			<value>
+				marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR
+				dianne=emu,ROLE_TELLER
+				scott=wombat,ROLE_TELLER
+				peter=opal,disabled,ROLE_TELLER
+			</value>
+		</property>
+	</bean>
+	
+	<!-- Authentication provider that queries our data access object  -->
+	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
+     	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
+ 		<property name="ignorePasswordCase"><value>false</value></property>
+ 		<property name="ignoreUsernameCase"><value>true</value></property>
+	</bean>
+
+	<!-- The authentication manager that iterates through our only authentication provider -->
+	<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
+		<property name="providers">
+		  <list>
+		    <ref bean="daoAuthenticationProvider"/>
+		  </list>
+		</property>
+	</bean>
+
+</beans>

+ 13 - 0
samples/contacts/etc/ca/resin-web.xml

@@ -0,0 +1,13 @@
+<!--
+  - $Id$
+  - File will be copied into WAR's WEB-INF directory if using container adapter
+  -->
+<web-app>
+      <authenticator>
+        <type>net.sf.acegisecurity.adapters.resin.ResinAcegiAuthenticator</type>
+        <init>
+          <app-context-location>resin-acegisecurity.xml</app-context-location>
+           <key>my_password</key>
+        </init>
+      </authenticator>
+</web-app>

+ 99 - 0
samples/contacts/etc/ca/web.xml

@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE web-app PUBLIC '-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN' 'http://java.sun.com/dtd/web-app_2_3.dtd'>
+
+<!--
+  - Contacts web application
+  - $Id$
+  - File will be copied into WAR's WEB-INF directory if using container adapter
+  -->
+
+<web-app>
+
+    <display-name>Contacts Sample Application</display-name>
+    
+	<description>
+    	Example of an application secured using Acegi Security System for Spring.
+    </description>
+
+    <filter>
+        <filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
+        <filter-class>net.sf.acegisecurity.ui.AutoIntegrationFilter</filter-class>
+    </filter>
+
+    <filter-mapping>
+      <filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
+      <url-pattern>/*</url-pattern>
+    </filter-mapping>
+
+  <!--
+    - Servlet that dispatches request to registered handlers (Controller implementations).
+    - Has its own application context, by default defined in "{servlet-name}-servlet.xml",
+    - i.e. "contacts-servlet.xml".
+    -
+    - A web app can contain any number of such servlets.
+    - Note that this web app does not have a shared root application context,
+    - therefore the DispatcherServlet contexts do not have a common parent.
+    -->
+	<servlet>
+		<servlet-name>contacts</servlet-name>
+		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+		<load-on-startup>1</load-on-startup>
+	</servlet>
+
+  <!--
+    - Maps the contacts dispatcher to /*.
+    -
+   -->
+	<servlet-mapping>
+    	<servlet-name>contacts</servlet-name>
+    	<url-pattern>*.htm</url-pattern>
+ 	</servlet-mapping>
+  
+ 	<welcome-file-list>
+		<welcome-file>index.jsp</welcome-file>
+	</welcome-file-list>
+
+  	<taglib>
+      <taglib-uri>/spring</taglib-uri>
+      <taglib-location>/WEB-INF/spring.tld</taglib-location>
+  	</taglib>
+
+    <security-constraint>
+      <display-name>Secured Area Security Constraint</display-name>
+      <web-resource-collection>
+         <web-resource-name>Secured Area</web-resource-name>
+         <url-pattern>/secure/*</url-pattern>
+      </web-resource-collection>
+      <auth-constraint>
+         <role-name>ROLE_TELLER</role-name>
+	     <role-name>ROLE_SUPERVISOR</role-name>
+      </auth-constraint>
+    </security-constraint>
+
+    <!-- Default login configuration using BASIC authentication -->
+	<!--
+	<login-config>
+      <auth-method>BASIC</auth-method>
+      <realm-name>Spring Powered Realm</realm-name>
+	</login-config>
+    -->
+  
+    <!-- Default login configuration using form-based authentication -->
+    <login-config>
+      <auth-method>FORM</auth-method>
+      <realm-name>Spring Powered Realm</realm-name>
+      <form-login-config>
+        <form-login-page>/login.jsp</form-login-page>
+        <form-error-page>/login.jsp?login_error=1</form-error-page>
+      </form-login-config>
+    </login-config>
+
+    <!-- Security roles referenced by this web application -->
+    <security-role>
+      <role-name>ROLE_SUPERVISOR</role-name>
+    </security-role>
+    <security-role>
+      <role-name>ROLE_TELLER</role-name>
+    </security-role>    
+
+</web-app>

+ 40 - 0
samples/contacts/etc/filter/acegilogin.jsp

@@ -0,0 +1,40 @@
+<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %>
+<%-- This page will be copied into WAR's root directory if NOT using container adapter --%>
+
+<html>
+  <head>
+    <title>Login</title>
+  </head>
+
+  <body>
+    <h1>Login</h1>
+
+	<P>If you've used the standard springsecurity.xml, try these users:
+	<P>
+	<P>username <b>marissa</b>, password <b>koala</b> (granted ROLE_SUPERVISOR)
+	<P>username <b>dianne</b>, password <b>emu</b> (not a supervisor)
+	<p>username <b>scott</b>, password <b>wombat</b> (not a supervisor)
+	<p>
+	
+    <%-- this form-login-page form is also used as the 
+         form-error-page to ask for a login again.
+         --%>
+    <c:if test="${not empty param.login_error}">
+      <font color="red">
+        Your login attempt was not successful, try again.
+      </font>
+    </c:if>
+
+    <form action="<c:url value='j_acegi_security_check'/>" method="POST">
+      <table>
+        <tr><td>User:</td><td><input type='text' name='j_username'></td></tr>
+        <tr><td>Password:</td><td><input type='password' name='j_password'></td></tr>
+
+        <tr><td colspan='2'><input name="submit" type="submit"></td></tr>
+        <tr><td colspan='2'><input name="reset" type="reset"></td></tr>
+      </table>
+
+    </form>
+
+  </body>
+</html>

+ 114 - 0
samples/contacts/etc/filter/web-filters-acegisecurity.xml

@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+<!--
+ * 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.
+ *
+ *
+ * $Id$
+ *
+ * This file will be copied into WAR's classes directory if NOT using container adapter
+-->
+
+<beans>
+
+	<!-- ==================== AUTHENTICATION DEFINITIONS =================== -->
+	
+	<!-- Data access object which stores authentication information -->
+	<bean id="inMemoryDaoImpl" class="net.sf.acegisecurity.providers.dao.memory.InMemoryDaoImpl">
+  		<property name="userMap">
+			<value>
+				marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR
+				dianne=emu,ROLE_TELLER
+				scott=wombat,ROLE_TELLER
+				peter=opal,disabled,ROLE_TELLER
+			</value>
+		</property>
+	</bean>
+	
+	<!-- Authentication provider that queries our data access object  -->
+	<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
+     	<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
+ 		<property name="ignorePasswordCase"><value>false</value></property>
+ 		<property name="ignoreUsernameCase"><value>true</value></property>
+	</bean>
+
+	<!-- The authentication manager that iterates through our only authentication provider -->
+	<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
+		<property name="providers">
+		  <list>
+		    <ref bean="daoAuthenticationProvider"/>
+		  </list>
+		</property>
+	</bean>
+	
+	<!-- ===================== HTTP REQUEST SECURITY ==================== -->
+
+	<bean id="runAsManager" class="net.sf.acegisecurity.runas.RunAsManagerImpl">
+     	<property name="key"><value>my_run_as_password</value></property>
+ 	</bean>
+
+	<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
+
+	<bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
+   		<property name="allowIfAllAbstainDecisions"><value>false</value></property>
+		<property name="decisionVoters">
+		  <list>
+		    <ref bean="roleVoter"/>
+		  </list>
+		</property>
+	</bean>
+
+	<!-- The FilterSecurityInterceptor is called by the web.xml-defined SecurityEnforcementFilter.
+	     Note the order that entries are placed against the objectDefinitionSource is critical.
+	     The FilterSecurityInterceptor will work from the top of the list down to the FIRST pattern that matches the request URL.
+	     Accordingly, you should place MOST SPECIFIC (ie a/b/c/d.*) expressions first, with LEAST SPECIFIC (ie a/.*) expressions last -->
+	
+	<bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor">
+    	<property name="authenticationManager"><ref bean="authenticationManager"/></property>
+    	<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
+    	<property name="runAsManager"><ref bean="runAsManager"/></property>
+ 		<property name="objectDefinitionSource">
+			<value>
+			    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
+				\A/secure/super.*\Z=ROLE_WE_DONT_HAVE
+				\A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_TELLER
+			</value>
+		</property>
+	</bean>
+	
+	<!-- BASIC Regular Expression Syntax (for beginners):
+	     
+	     \A means the start of the string (ie the beginning of the URL)
+	     \Z means the end of the string (ie the end of the URL)
+	     .  means any single character
+	     *  means null or any number of repetitions of the last expression (so .* means zero or more characters)
+	     
+	     Some examples:
+	     
+	     Expression:   \A/my/directory/.*\Z
+	     Would match:    /my/directory/
+	                     /my/directory/hello.html
+	     
+	     Expression:   \A/.*\Z
+	     Would match:    /hello.html
+	                     /
+	     
+	     Expression:   \A/.*/secret.html\Z
+	     Would match:    /some/directory/secret.html
+	                     /another/secret.html
+	     Not match:      /anothersecret.html (missing required /)
+	-->
+
+</beans>

+ 108 - 0
samples/contacts/etc/filter/web.xml

@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE web-app PUBLIC '-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN' 'http://java.sun.com/dtd/web-app_2_3.dtd'>
+
+<!--
+  - Contacts web application
+  - $Id$
+  - File will be copied into WAR's WEB-INF directory if NOT using container adapter
+  -->
+
+<web-app>
+
+    <display-name>Contacts Sample Application</display-name>
+    
+	<description>
+    	Example of an application secured using Acegi Security System for Spring.
+    </description>
+
+
+    <filter>
+        <filter-name>Acegi Authentication Processing Filter</filter-name>
+        <filter-class>net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter</filter-class>
+        <init-param>
+            <param-name>appContextLocation</param-name>
+            <param-value>web-filters-acegisecurity.xml</param-value>
+        </init-param>
+        <init-param>
+            <param-name>authenticationFailureUrl</param-name>
+            <param-value>/acegilogin.jsp?login_error=1</param-value>
+        </init-param>
+        <init-param>
+              <param-name>defaultTargetUrl</param-name>
+              <param-value>/</param-value>
+        </init-param>
+        <init-param>
+            <param-name>filterProcessUrl</param-name>
+            <param-value>/j_acegi_security_check</param-value>
+        </init-param>
+    </filter>
+
+
+    <filter>
+        <filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
+        <filter-class>net.sf.acegisecurity.ui.AutoIntegrationFilter</filter-class>
+    </filter>
+
+   
+    <filter>
+        <filter-name>Acegi HTTP Request Security Filter</filter-name>
+        <filter-class>net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter</filter-class>
+        <init-param>
+            <param-name>appContextLocation</param-name>
+            <param-value>web-filters-acegisecurity.xml</param-value>
+        </init-param>
+        <init-param>
+            <param-name>loginFormUrl</param-name>
+            <param-value>/acegilogin.jsp</param-value>
+        </init-param>
+    </filter>
+
+    <filter-mapping>
+      <filter-name>Acegi Authentication Processing Filter</filter-name>
+      <url-pattern>/*</url-pattern>
+    </filter-mapping>
+
+    <filter-mapping>
+      <filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
+      <url-pattern>/*</url-pattern>
+    </filter-mapping>
+    
+    <filter-mapping>
+      <filter-name>Acegi HTTP Request Security Filter</filter-name>
+      <url-pattern>/*</url-pattern>
+    </filter-mapping>
+
+  <!--
+    - Servlet that dispatches request to registered handlers (Controller implementations).
+    - Has its own application context, by default defined in "{servlet-name}-servlet.xml",
+    - i.e. "contacts-servlet.xml".
+    -
+    - A web app can contain any number of such servlets.
+    - Note that this web app does not have a shared root application context,
+    - therefore the DispatcherServlet contexts do not have a common parent.
+    -->
+	<servlet>
+		<servlet-name>contacts</servlet-name>
+		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+		<load-on-startup>1</load-on-startup>
+	</servlet>
+
+  <!--
+    - Maps the contacts dispatcher to /*.
+    -
+   -->
+	<servlet-mapping>
+    	<servlet-name>contacts</servlet-name>
+    	<url-pattern>*.htm</url-pattern>
+ 	</servlet-mapping>
+  
+ 	<welcome-file-list>
+		<welcome-file>index.jsp</welcome-file>
+	</welcome-file-list>
+
+  	<taglib>
+      <taglib-uri>/spring</taglib-uri>
+      <taglib-location>/WEB-INF/spring.tld</taglib-location>
+  	</taglib>
+  
+</web-app>