Initial commit.
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
classes
|
||||
generated
|
||||
reports
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!--
|
||||
Build file for the "attributes" sample application.
|
||||
|
||||
Demonstrates how to compile an application that has the security
|
||||
configuration defined by Commons Attributes in its Java source code.
|
||||
|
||||
$Id$
|
||||
-->
|
||||
|
||||
<project name="attributes" default="all" basedir=".">
|
||||
|
||||
<property file="build.properties"/>
|
||||
<property file="project.properties"/>
|
||||
|
||||
<path id="attribute-compiler-classpath">
|
||||
<fileset dir="${lib.dir}">
|
||||
<include name="**/commons-attributes-compiler-SNAPSHOT.jar"/>
|
||||
<include name="**/commons-collections.jar"/>
|
||||
<include name="**/xjavadoc-1.0.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<path id="qa-portalpath">
|
||||
<pathelement location="classes"/>
|
||||
<fileset dir="${dist.lib.dir}">
|
||||
<include name="acegi-security.jar"/>
|
||||
</fileset>
|
||||
<fileset dir="${lib.dir}">
|
||||
<include name="**/spring.jar"/>
|
||||
<include name="**/aopalliance.jar"/>
|
||||
<include name="**/commons-logging.jar"/>
|
||||
<include name="**/commons-attributes-api-SNAPSHOT.jar"/>
|
||||
<include name="**/commons-collections.jar"/>
|
||||
<include name="**/xml-apis.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<path id="jalopy-classpath">
|
||||
<fileset dir="${lib.dir}/jalopy">
|
||||
<include name="**/*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<target name="attribute-compiler" description="Generate Commons Attributes sources from original sources">
|
||||
<taskdef name='attribute-compiler'
|
||||
classname="org.apache.commons.attributes.compiler.AttributeCompiler"
|
||||
classpathref="attribute-compiler-classpath"/>
|
||||
<attribute-compiler
|
||||
destdir="${src.generated.dir}"
|
||||
attributePackages="net.sf.acegisecurity">
|
||||
<fileset dir="${src.dir}"/>
|
||||
</attribute-compiler>
|
||||
</target>
|
||||
|
||||
<target name="compile-classes" description="Compile generated and original sources">
|
||||
<mkdir dir="${build.dir}"/>
|
||||
<javac destdir="${build.dir}" classpathref="qa-portalpath">
|
||||
<src path="${src.dir}"/>
|
||||
<src path="${src.generated.dir}"/>
|
||||
</javac>
|
||||
<copy todir="${build.dir}">
|
||||
<fileset dir="${src.dir}">
|
||||
<include name="*.xml"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="format" description="Formats all project source code">
|
||||
<taskdef name="jalopy" classname="de.hunsicker.jalopy.plugin.ant.AntPlugin">
|
||||
<classpath refid="jalopy-classpath"/>
|
||||
</taskdef>
|
||||
|
||||
<jalopy fileformat="unix"
|
||||
convention="${jalopy.xml}"
|
||||
history="file"
|
||||
historymethod="adler32"
|
||||
loglevel="error"
|
||||
threads="2"
|
||||
classpathref="qa-portalpath">
|
||||
<fileset dir="${src.dir}">
|
||||
<include name="**/*.java"/>
|
||||
</fileset>
|
||||
</jalopy>
|
||||
</target>
|
||||
|
||||
<target name="tests" depends="compile-classes" description="Run tests">
|
||||
|
||||
<delete dir="${reports.dir}"/>
|
||||
<mkdir dir="${reports.dir}"/>
|
||||
|
||||
<junit printsummary="yes" haltonfailure="yes">
|
||||
<classpath location="${build.dir}"/>
|
||||
<classpath refid="qa-portalpath"/>
|
||||
<formatter type="plain"/>
|
||||
|
||||
<batchtest fork="yes" todir="${reports.dir}">
|
||||
<fileset dir="${build.dir}" includes="${test.includes}" excludes="${test.excludes}"/>
|
||||
</batchtest>
|
||||
</junit>
|
||||
|
||||
</target>
|
||||
|
||||
<target name="clean" description="Clean output dirs (generated, classes, reports)">
|
||||
<delete dir="${src.generated.dir}"/>
|
||||
<delete dir="${build.dir}"/>
|
||||
<delete dir="${reports.dir}"/>
|
||||
</target>
|
||||
|
||||
<target name="all" depends="clean, attribute-compiler, compile-classes, tests" description="Builds from scratch and runs tests"/>
|
||||
|
||||
<target name="execute" description="Runs application (assumes has been built)">
|
||||
<java fork="true" qa-portalpathref="qa-portalpath" classname="sample.attributes.Main"/>
|
||||
</target>
|
||||
|
||||
<target name="release" depends="all" description="Builds a clean release file"/>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
# Ant properties for building the Attributes sample application.
|
||||
# $Id$
|
||||
|
||||
name=attributes
|
||||
src.dir=src
|
||||
src.generated.dir=generated
|
||||
lib.dir=${basedir}/../../lib
|
||||
dist.lib.dir=${basedir}/../../dist
|
||||
build.dir=classes
|
||||
jalopy.xml=${basedir}/../../jalopy.xml
|
||||
reports.dir=reports
|
||||
test.includes=**/*TestSuite.class **/*Tests.class
|
||||
test.excludes=**/Abstract*
|
||||
@@ -0,0 +1,81 @@
|
||||
<?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.
|
||||
* $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- =================== SECURITY SYSTEM DEFINITIONS ================== -->
|
||||
|
||||
<!-- RunAsManager -->
|
||||
<bean id="runAsManager" class="net.sf.acegisecurity.runas.RunAsManagerImpl">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHENTICATION DEFINITIONS ~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- This authentication provider accepts any presented TestingAuthenticationToken -->
|
||||
<bean id="testingAuthenticationProvider" class="net.sf.acegisecurity.providers.TestingAuthenticationProvider"/>
|
||||
|
||||
<!-- 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="testingAuthenticationProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- An access decision voter that reads ROLE_* configuaration settings -->
|
||||
<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
|
||||
|
||||
<!-- A unanimous access decision manager -->
|
||||
<bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.UnanimousBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref bean="roleVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ===================== SECURITY DEFINITIONS ======================= -->
|
||||
|
||||
<bean id="attributes" class="org.springframework.metadata.commons.CommonsAttributes"/>
|
||||
<bean id="methodDefinitionSource" class="net.sf.acegisecurity.MethodDefinitionAttributes">
|
||||
<property name="attributes"><ref local="attributes"/></property>
|
||||
</bean>
|
||||
|
||||
<!-- We don't validate config attributes, as it's unsupported by MethodDefinitionAttributes -->
|
||||
<bean id="securityInterceptor" class="net.sf.acegisecurity.SecurityInterceptor">
|
||||
<property name="validateConfigAttributes"><value>false</value></property>
|
||||
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref bean="runAsManager"/></property>
|
||||
<property name="methodDefinitionSource"><ref bean="methodDefinitionSource"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="bankService" class="sample.attributes.BankServiceImpl"/>
|
||||
|
||||
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
|
||||
<!-- names of the interceptors that will be applied by the proxy -->
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>securityInterceptor</value>
|
||||
</list>
|
||||
</property>
|
||||
|
||||
<!-- the bean names to automatically generate proxies for -->
|
||||
<property name="beanNames">
|
||||
<list>
|
||||
<value>bankService</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.attributes;
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author Cameron Braid
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*
|
||||
* @@SecurityConfig("ROLE_TELLER")
|
||||
*/
|
||||
public interface BankService {
|
||||
//~ Methods ================================================================
|
||||
|
||||
/**
|
||||
* The SecurityConfig below will be merged with the interface-level
|
||||
* SecurityConfig above by Commons Attributes. ie: this is equivalent to
|
||||
* defining BankService=ROLE_TELLER,ROLE_PERMISSION_BALANACE in the bean
|
||||
* context.
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @@SecurityConfig("ROLE_PERMISSION_BALANCE")
|
||||
*/
|
||||
public float balance(String accountNumber);
|
||||
|
||||
/**
|
||||
* The SecurityConfig below will be merged with the interface-level
|
||||
* SecurityConfig above by Commons Attributes. ie: this is equivalent to
|
||||
* defining BankService=ROLE_TELLER,ROLE_PERMISSION_LIST in the bean
|
||||
* context.
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @@SecurityConfig("ROLE_PERMISSION_LIST")
|
||||
*/
|
||||
public String[] listAccounts();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.attributes;
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author Cameron Braid
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BankServiceImpl implements BankService {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public float balance(String accountNumber) {
|
||||
return 42000000;
|
||||
}
|
||||
|
||||
public String[] listAccounts() {
|
||||
return new String[] {"1", "2", "3"};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.attributes;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.AccessDeniedException;
|
||||
import net.sf.acegisecurity.GrantedAuthority;
|
||||
import net.sf.acegisecurity.GrantedAuthorityImpl;
|
||||
import net.sf.acegisecurity.context.ContextHolder;
|
||||
import net.sf.acegisecurity.context.SecureContextImpl;
|
||||
import net.sf.acegisecurity.providers.TestingAuthenticationToken;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* Tests security objects.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BankTests extends TestCase {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private BankService service;
|
||||
private ClassPathXmlApplicationContext ctx;
|
||||
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public BankTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public BankTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
|
||||
service = (BankService) ctx.getBean("bankService");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(BankTests.class);
|
||||
}
|
||||
|
||||
public void testDeniedAccess() throws Exception {
|
||||
createSecureContext();
|
||||
|
||||
try {
|
||||
service.balance("1");
|
||||
fail("Should have thrown AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
destroySecureContext();
|
||||
}
|
||||
|
||||
public void testListAccounts() throws Exception {
|
||||
createSecureContext();
|
||||
service.listAccounts();
|
||||
destroySecureContext();
|
||||
}
|
||||
|
||||
private static void createSecureContext() {
|
||||
TestingAuthenticationToken auth = new TestingAuthenticationToken("test",
|
||||
"test",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_TELLER"), new GrantedAuthorityImpl("ROLE_PERMISSION_LIST")});
|
||||
|
||||
SecureContextImpl secureContext = new SecureContextImpl();
|
||||
secureContext.setAuthentication(auth);
|
||||
ContextHolder.setContext(secureContext);
|
||||
}
|
||||
|
||||
private static void destroySecureContext() {
|
||||
ContextHolder.setContext(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.attributes;
|
||||
|
||||
import net.sf.acegisecurity.AccessDeniedException;
|
||||
import net.sf.acegisecurity.GrantedAuthority;
|
||||
import net.sf.acegisecurity.GrantedAuthorityImpl;
|
||||
import net.sf.acegisecurity.context.ContextHolder;
|
||||
import net.sf.acegisecurity.context.SecureContextImpl;
|
||||
import net.sf.acegisecurity.providers.TestingAuthenticationToken;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author Cameron Braid
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class Main {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
createSecureContext();
|
||||
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
|
||||
BankService service = (BankService) context.getBean("bankService");
|
||||
|
||||
// will succeed
|
||||
service.listAccounts();
|
||||
|
||||
// will fail
|
||||
try {
|
||||
System.out.println("We expect an AccessDeniedException now, as we do not hold the ROLE_PERMISSION_BALANCE granted authority, and we're using a unanimous access decision manager... ");
|
||||
service.balance("1");
|
||||
} catch (AccessDeniedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
destroySecureContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* This can be done in a web app by using a filter or
|
||||
* <code>SpringMvcIntegrationInterceptor</code>.
|
||||
*/
|
||||
private static void createSecureContext() {
|
||||
TestingAuthenticationToken auth = new TestingAuthenticationToken("test",
|
||||
"test",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_TELLER"), new GrantedAuthorityImpl("ROLE_PERMISSION_LIST")});
|
||||
|
||||
SecureContextImpl secureContext = new SecureContextImpl();
|
||||
secureContext.setAuthentication(auth);
|
||||
ContextHolder.setContext(secureContext);
|
||||
}
|
||||
|
||||
private static void destroySecureContext() {
|
||||
ContextHolder.setContext(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
classes
|
||||
dist
|
||||
api
|
||||
build.properties
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!--
|
||||
Build file for the "contacts" sample application.
|
||||
$Id$
|
||||
-->
|
||||
|
||||
<project name="minimal" basedir="." default="usage">
|
||||
|
||||
<property file="build.properties"/>
|
||||
<property file="project.properties"/>
|
||||
|
||||
<path id="qa-portalpath">
|
||||
<fileset dir="${dist.lib.dir}">
|
||||
<include name="acegi-security.jar"/>
|
||||
</fileset>
|
||||
<fileset dir="${lib.dir}">
|
||||
<include name="**/**.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<path id="jalopy-classpath">
|
||||
<fileset dir="${lib.dir}/jalopy">
|
||||
<include name="**/*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<target name="usage">
|
||||
<echo message=""/>
|
||||
<echo message="Contacts sample application build file"/>
|
||||
<echo message="*** Make sure you've copied the required JAR files to the lib directory."/>
|
||||
<echo message="*** See lib/readme.txt for more information."/>
|
||||
<echo message="------------------------------------------------------"/>
|
||||
<echo message=""/>
|
||||
<echo message="Available targets are:"/>
|
||||
<echo message=""/>
|
||||
<echo message="clean --> Clean output dirs"/>
|
||||
<echo message="build --> Compile main Java sources and copy libraries"/>
|
||||
<echo message="warfile --> Create WAR deployment units"/>
|
||||
<echo message="javadoc --> Create API documentation"/>
|
||||
<echo message=""/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="clean" description="Clean output dirs (build, dist)">
|
||||
<delete dir="${build.dir}"/>
|
||||
<delete dir="${dist.dir}"/>
|
||||
<delete dir="${war.dir}/WEB-INF/lib"/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="build" description="Compile main source tree java files into class files">
|
||||
<mkdir dir="${build.dir}"/>
|
||||
|
||||
<javac destdir="${build.dir}" target="1.3" debug="true" deprecation="false"
|
||||
optimize="false" failonerror="true">
|
||||
<src path="${src.dir}"/>
|
||||
<classpath refid="qa-portalpath"/>
|
||||
</javac>
|
||||
|
||||
<copy todir="${build.dir}">
|
||||
<fileset dir="${src.dir}">
|
||||
<include name="*.properties"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="format" description="Formats all project source code">
|
||||
<taskdef name="jalopy" classname="de.hunsicker.jalopy.plugin.ant.AntPlugin">
|
||||
<classpath refid="jalopy-classpath"/>
|
||||
</taskdef>
|
||||
|
||||
<jalopy fileformat="unix"
|
||||
convention="${jalopy.xml}"
|
||||
history="file"
|
||||
historymethod="adler32"
|
||||
loglevel="error"
|
||||
threads="2"
|
||||
classpathref="qa-portalpath">
|
||||
<fileset dir="${src.dir}">
|
||||
<include name="**/*.java"/>
|
||||
</fileset>
|
||||
</jalopy>
|
||||
</target>
|
||||
|
||||
<target name="warfile" depends="build" description="Build the web application archives">
|
||||
<mkdir dir="${dist.dir}"/>
|
||||
|
||||
<!-- Temporary staging directory for libs -->
|
||||
<delete dir="${war.dir}/WEB-INF/lib"/>
|
||||
<mkdir dir="${war.dir}/WEB-INF/lib"/>
|
||||
|
||||
<!-- Copy required libs into temporary staging directory -->
|
||||
<copy todir="${war.dir}/WEB-INF/lib">
|
||||
<fileset dir="${lib.dir}/jakarta-taglibs">
|
||||
<include name="standard.jar"/>
|
||||
</fileset>
|
||||
<fileset dir="${lib.dir}/j2ee">
|
||||
<include name="jstl.jar"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<war warfile="${dist.dir}/${name}.war" webxml="${war.dir}/WEB-INF/web.xml">
|
||||
<!-- Include the JSPs and other documents -->
|
||||
<fileset dir="war" excludes="WEB-INF/**"/>
|
||||
|
||||
<!-- Bring in Spring-specific XML configuration files -->
|
||||
<webinf dir="${war.dir}/WEB-INF">
|
||||
<!-- We separately include these -->
|
||||
<exclude name="web.xml"/>
|
||||
<exclude name="lib/**"/>
|
||||
</webinf>
|
||||
|
||||
<!-- Include the compiled classes -->
|
||||
<classes dir="${build.dir}"/>
|
||||
|
||||
<!-- Include the temporary staging directory for libs -->
|
||||
<lib dir = "${war.dir}/WEB-INF/lib"/>
|
||||
</war>
|
||||
|
||||
<!-- Remove temporary staging directory -->
|
||||
<delete dir="${war.dir}/WEB-INF/lib"/>
|
||||
|
||||
</target>
|
||||
|
||||
<target name="javadoc" description="Generate Javadocs.">
|
||||
<mkdir dir="${javadocs.dir}"/>
|
||||
|
||||
<javadoc sourcepath="src" destdir="${javadocs.dir}" windowtitle="Contact Sample Application"
|
||||
defaultexcludes="yes" author="true" version="true" use="true">
|
||||
<doctitle><![CDATA[<h1>Acegi Security System for Spring Contacts Sample</h1>]]></doctitle>
|
||||
<bottom><![CDATA[<A HREF="http://acegisecurity.sourceforge.net">Acegi Security System for Spring Project]]></bottom>
|
||||
<classpath refid="qa-portalpath"/>
|
||||
<packageset dir="${src.dir}">
|
||||
<include name="sample/contact/**"/>
|
||||
</packageset>
|
||||
</javadoc>
|
||||
</target>
|
||||
|
||||
<target name="release" depends="clean,warfile,javadoc" description="Builds a clean release file"/>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,12 @@
|
||||
# Ant properties for building the Contacts sample application.
|
||||
# $Id$
|
||||
|
||||
name=contacts
|
||||
src.dir=src
|
||||
war.dir=war
|
||||
lib.dir=${basedir}/../../lib
|
||||
dist.lib.dir=${basedir}/../../dist
|
||||
build.dir=classes
|
||||
dist.dir=dist
|
||||
javadocs.dir=api
|
||||
jalopy.xml=${basedir}/../../jalopy.xml
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
/**
|
||||
* Represents a contact.
|
||||
*
|
||||
* <P>
|
||||
* <code>id</code> and <code>owner</code> are immutable.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class Contact {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private Integer id;
|
||||
private String email;
|
||||
private String name;
|
||||
private String owner;
|
||||
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public Contact(Integer id, String name, String email, String owner) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
private Contact() {
|
||||
super();
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @param email The email to set.
|
||||
*/
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @return Returns the email.
|
||||
*/
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @return Returns the id.
|
||||
*/
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @param name The name to set.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @return Returns the name.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @return Returns the owner.
|
||||
*/
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(super.toString() + ": ");
|
||||
sb.append("Id: " + this.getId() + "; ");
|
||||
sb.append("Name: " + this.getName() + "; ");
|
||||
sb.append("Email: " + this.getEmail() + "; ");
|
||||
sb.append("Owner: " + this.getOwner());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
/**
|
||||
* Iterface for the application's business object.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface ContactManager {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public Contact[] getAllByOwner(String owner);
|
||||
|
||||
public Contact getById(Integer id);
|
||||
|
||||
public Integer getNextId();
|
||||
|
||||
public Contact getRandomContact();
|
||||
|
||||
public void delete(Contact contact);
|
||||
|
||||
public void save(Contact contact);
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
/**
|
||||
* Backend business object that manages the contacts.
|
||||
*
|
||||
* <P>
|
||||
* As a backend, it never faces the public callers. It is always accessed via
|
||||
* the {@link ContactManagerFacade}.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* This facade approach is not really necessary in this application, and is
|
||||
* done simply to demonstrate granting additional authorities via the
|
||||
* <code>RunAsManager</code>.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ContactManagerBackend implements ContactManager {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private Map contacts;
|
||||
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public ContactManagerBackend() {
|
||||
this.contacts = new HashMap();
|
||||
save(new Contact(this.getNextId(), "John Smith", "john@somewhere.com",
|
||||
"marissa"));
|
||||
save(new Contact(this.getNextId(), "Michael Citizen",
|
||||
"michael@xyz.com", "marissa"));
|
||||
save(new Contact(this.getNextId(), "Joe Bloggs", "joe@demo.com",
|
||||
"marissa"));
|
||||
save(new Contact(this.getNextId(), "Karen Sutherland",
|
||||
"karen@sutherland.com", "dianne"));
|
||||
save(new Contact(this.getNextId(), "Mitchell Howard",
|
||||
"mitchell@abcdef.com", "dianne"));
|
||||
save(new Contact(this.getNextId(), "Rose Costas", "rose@xyz.com",
|
||||
"scott"));
|
||||
save(new Contact(this.getNextId(), "Amanda Smith", "amanda@abcdef.com",
|
||||
"scott"));
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
/**
|
||||
* Security system expects ROLE_RUN_AS_SERVER
|
||||
*
|
||||
* @param owner DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*/
|
||||
public Contact[] getAllByOwner(String owner) {
|
||||
List list = new Vector();
|
||||
Iterator iter = this.contacts.keySet().iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
Integer contactId = (Integer) iter.next();
|
||||
Contact contact = (Contact) this.contacts.get(contactId);
|
||||
|
||||
if (contact.getOwner().equals(owner)) {
|
||||
list.add(contact);
|
||||
}
|
||||
}
|
||||
|
||||
Contact[] resultType = {new Contact(new Integer(1), "holder", "holder",
|
||||
"holder")};
|
||||
|
||||
if (list.size() == 0) {
|
||||
return null;
|
||||
} else {
|
||||
return (Contact[]) list.toArray(resultType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Security system expects ROLE_RUN_AS_SERVER
|
||||
*
|
||||
* @param id DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*/
|
||||
public Contact getById(Integer id) {
|
||||
return (Contact) this.contacts.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public method
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*/
|
||||
public Integer getNextId() {
|
||||
int max = 0;
|
||||
Iterator iter = this.contacts.keySet().iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
Integer id = (Integer) iter.next();
|
||||
|
||||
if (id.intValue() > max) {
|
||||
max = id.intValue();
|
||||
}
|
||||
}
|
||||
|
||||
return new Integer(max + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a public method, meaning a client could call this method
|
||||
* directly (ie not via a facade). If this was an issue, the public method
|
||||
* on the facade should not be public but secure. Quite possibly an
|
||||
* AnonymousAuthenticationToken and associated provider could be used on a
|
||||
* secure method, thus allowing a RunAsManager to protect the backend.
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*/
|
||||
public Contact getRandomContact() {
|
||||
Random rnd = new Random();
|
||||
int getNumber = rnd.nextInt(this.contacts.size()) + 1;
|
||||
Iterator iter = this.contacts.keySet().iterator();
|
||||
int i = 0;
|
||||
|
||||
while (iter.hasNext()) {
|
||||
i++;
|
||||
|
||||
Integer id = (Integer) iter.next();
|
||||
|
||||
if (i == getNumber) {
|
||||
return (Contact) this.contacts.get(id);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Security system expects ROLE_RUN_AS_SERVER
|
||||
*
|
||||
* @param contact DOCUMENT ME!
|
||||
*/
|
||||
public void delete(Contact contact) {
|
||||
this.contacts.remove(contact.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Security system expects ROLE_RUN_AS_SERVER
|
||||
*
|
||||
* @param contact DOCUMENT ME!
|
||||
*/
|
||||
public void save(Contact contact) {
|
||||
this.contacts.put(contact.getId(), contact);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import net.sf.acegisecurity.AccessDeniedException;
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.context.ContextHolder;
|
||||
import net.sf.acegisecurity.context.SecureContext;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
|
||||
/**
|
||||
* This is the public facade to the application's main business object.
|
||||
*
|
||||
* <p>
|
||||
* Used to demonstrate security configuration in a multi-tier application. Most
|
||||
* methods of this class are secured via standard security definitions in the
|
||||
* bean context. There is one method that supplements these security checks.
|
||||
* All methods delegate to a "backend" object. The "backend" object relies on
|
||||
* the facade's <code>RunAsManager</code> assigning an additional
|
||||
* <code>GrantedAuthority</code> that is required to call its methods.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ContactManagerFacade implements ContactManager, InitializingBean {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ContactManager backend;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
/**
|
||||
* Security system will ensure the owner parameter equals the currently
|
||||
* logged in user.
|
||||
*
|
||||
* @param owner DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*/
|
||||
public Contact[] getAllByOwner(String owner) {
|
||||
return backend.getAllByOwner(owner);
|
||||
}
|
||||
|
||||
public void setBackend(ContactManager backend) {
|
||||
this.backend = backend;
|
||||
}
|
||||
|
||||
public ContactManager getBackend() {
|
||||
return backend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Security system will ensure logged in user has ROLE_TELLER.
|
||||
*
|
||||
* <p>
|
||||
* Security system cannot ensure that only the owner can get the contact,
|
||||
* as doing so would require it to specifically open the contact. Whilst
|
||||
* possible, this would be expensive as the operation would be performed
|
||||
* both by the security system as well as the implementation. Instead the
|
||||
* facade will confirm the contact.getOwner() matches what is on the
|
||||
* ContextHolder.
|
||||
* </p>
|
||||
*
|
||||
* @param id DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws AccessDeniedException DOCUMENT ME!
|
||||
*/
|
||||
public Contact getById(Integer id) {
|
||||
Contact result = backend.getById(id);
|
||||
Authentication auth = ((SecureContext) ContextHolder.getContext())
|
||||
.getAuthentication();
|
||||
|
||||
if (auth.getPrincipal().toString().equals(result.getOwner())) {
|
||||
return result;
|
||||
} else {
|
||||
throw new AccessDeniedException("The requested id is not owned by the currently logged in user");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Public method.
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*/
|
||||
public Integer getNextId() {
|
||||
return backend.getNextId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Public method.
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*/
|
||||
public Contact getRandomContact() {
|
||||
return backend.getRandomContact();
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (backend == null) {
|
||||
throw new IllegalArgumentException("A backend ContactManager implementation is required");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Security system will ensure logged in user has ROLE_SUPERVISOR.
|
||||
*
|
||||
* @param contact DOCUMENT ME!
|
||||
*/
|
||||
public void delete(Contact contact) {
|
||||
backend.delete(contact);
|
||||
}
|
||||
|
||||
/**
|
||||
* Security system will ensure the owner specified via contact.getOwner()
|
||||
* equals the currently logged in user.
|
||||
*
|
||||
* @param contact DOCUMENT ME!
|
||||
*/
|
||||
public void save(Contact contact) {
|
||||
backend.save(contact);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.ConfigAttribute;
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
import net.sf.acegisecurity.vote.AccessDecisionVoter;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of an {@link AccessDecisionVoter} that provides
|
||||
* application-specific security for the Contact application.
|
||||
*
|
||||
* <p>
|
||||
* If the {@link ConfigAttribute#getAttribute()} has a value of
|
||||
* <code>CONTACT_OWNED_BY_CURRENT_USER</code>, the String or the
|
||||
* Contact.getOwner() associated with the method call is compared with the
|
||||
* Authentication.getPrincipal().toString() result. If it matches, the voter
|
||||
* votes to grant access. If they do not match, it votes to deny access.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* All comparisons are case sensitive.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ContactSecurityVoter implements AccessDecisionVoter {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if ("CONTACT_OWNED_BY_CURRENT_USER".equals(attribute.getAttribute())) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int vote(Authentication authentication, MethodInvocation invocation,
|
||||
ConfigAttributeDefinition config) {
|
||||
int result = ACCESS_ABSTAIN;
|
||||
Iterator iter = config.getConfigAttributes();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attribute = (ConfigAttribute) iter.next();
|
||||
|
||||
if (this.supports(attribute)) {
|
||||
result = ACCESS_DENIED;
|
||||
|
||||
// Lookup the account number being passed
|
||||
String passedOwner = null;
|
||||
|
||||
for (int i = 0; i < invocation.getArgumentCount(); i++) {
|
||||
Class argClass = invocation.getArgument(i).getClass();
|
||||
|
||||
if (String.class.isAssignableFrom(argClass)) {
|
||||
passedOwner = (String) invocation.getArgument(i);
|
||||
} else if (Contact.class.isAssignableFrom(argClass)) {
|
||||
passedOwner = ((Contact) invocation.getArgument(i))
|
||||
.getOwner();
|
||||
}
|
||||
}
|
||||
|
||||
if (passedOwner != null) {
|
||||
// Check the authentication principal matches the passed owner
|
||||
if (passedOwner.equals(authentication.getPrincipal()
|
||||
.toString())) {
|
||||
return ACCESS_GRANTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.Controller;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Controller to delete a contact page.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class DeleteController implements Controller, InitializingBean {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ContactManager contactManager;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setContactManager(ContactManager contact) {
|
||||
this.contactManager = contact;
|
||||
}
|
||||
|
||||
public ContactManager getContactManager() {
|
||||
return contactManager;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (contactManager == null) {
|
||||
throw new IllegalArgumentException("A ContactManager implementation is required");
|
||||
}
|
||||
}
|
||||
|
||||
public ModelAndView handleRequest(HttpServletRequest request,
|
||||
HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
Integer id = new Integer(request.getParameter("id"));
|
||||
Contact contact = contactManager.getById(id);
|
||||
contactManager.delete(contact);
|
||||
|
||||
return new ModelAndView("deleted", "contact", contact);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.Controller;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Controller for public index page (default web app home page).
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PublicIndexController implements Controller, InitializingBean {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ContactManager contactManager;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setContactManager(ContactManager contact) {
|
||||
this.contactManager = contact;
|
||||
}
|
||||
|
||||
public ContactManager getContactManager() {
|
||||
return contactManager;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (contactManager == null) {
|
||||
throw new IllegalArgumentException("A ContactManager implementation is required");
|
||||
}
|
||||
}
|
||||
|
||||
public ModelAndView handleRequest(HttpServletRequest request,
|
||||
HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
Contact rnd = contactManager.getRandomContact();
|
||||
|
||||
return new ModelAndView("hello", "contact", rnd);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.GrantedAuthority;
|
||||
import net.sf.acegisecurity.context.ContextHolder;
|
||||
import net.sf.acegisecurity.context.SecureContext;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.Controller;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Controller for secure index page.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecureIndexController implements Controller, InitializingBean {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ContactManager contactManager;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setContactManager(ContactManager contact) {
|
||||
this.contactManager = contact;
|
||||
}
|
||||
|
||||
public ContactManager getContactManager() {
|
||||
return contactManager;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (contactManager == null) {
|
||||
throw new IllegalArgumentException("A ContactManager implementation is required");
|
||||
}
|
||||
}
|
||||
|
||||
public ModelAndView handleRequest(HttpServletRequest request,
|
||||
HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
Authentication currentUser = ((SecureContext) ContextHolder.getContext())
|
||||
.getAuthentication();
|
||||
|
||||
boolean supervisor = false;
|
||||
GrantedAuthority[] granted = currentUser.getAuthorities();
|
||||
|
||||
for (int i = 0; i < granted.length; i++) {
|
||||
if (granted[i].getAuthority().equals("ROLE_SUPERVISOR")) {
|
||||
supervisor = true;
|
||||
}
|
||||
}
|
||||
|
||||
Contact[] myContacts = contactManager.getAllByOwner(currentUser.getPrincipal()
|
||||
.toString());
|
||||
|
||||
Map model = new HashMap();
|
||||
model.put("contacts", myContacts);
|
||||
model.put("supervisor", new Boolean(supervisor));
|
||||
model.put("user", currentUser.getPrincipal().toString());
|
||||
|
||||
return new ModelAndView("index", "model", model);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
/**
|
||||
* An object that represents user-editable sections of a {@link Contact}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class WebContact {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private String email;
|
||||
private String name;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import net.sf.acegisecurity.context.ContextHolder;
|
||||
import net.sf.acegisecurity.context.SecureContext;
|
||||
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.SimpleFormController;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Controller for adding a new contact.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class WebContactAddController extends SimpleFormController {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ContactManager contactManager;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setContactManager(ContactManager contactManager) {
|
||||
this.contactManager = contactManager;
|
||||
}
|
||||
|
||||
public ContactManager getContactManager() {
|
||||
return contactManager;
|
||||
}
|
||||
|
||||
public ModelAndView onSubmit(Object command) throws ServletException {
|
||||
String name = ((WebContact) command).getName();
|
||||
String email = ((WebContact) command).getEmail();
|
||||
String owner = ((SecureContext) ContextHolder.getContext()).getAuthentication()
|
||||
.getPrincipal().toString();
|
||||
|
||||
Contact contact = new Contact(contactManager.getNextId(), name, email,
|
||||
owner);
|
||||
contactManager.save(contact);
|
||||
|
||||
Map myModel = new HashMap();
|
||||
myModel.put("now", new Date());
|
||||
|
||||
return new ModelAndView(new RedirectView(getSuccessView()));
|
||||
}
|
||||
|
||||
protected Object formBackingObject(HttpServletRequest request)
|
||||
throws ServletException {
|
||||
WebContact wc = new WebContact();
|
||||
|
||||
return wc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.Validator;
|
||||
|
||||
|
||||
/**
|
||||
* Validates {@link WebContact}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class WebContactValidator implements Validator {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public boolean supports(Class clazz) {
|
||||
return clazz.equals(WebContact.class);
|
||||
}
|
||||
|
||||
public void validate(Object obj, Errors errors) {
|
||||
WebContact wc = (WebContact) obj;
|
||||
|
||||
if ((wc.getName() == null) || (wc.getName().length() < 3)) {
|
||||
errors.rejectValue("name", "not-used", null, "Name is required.");
|
||||
}
|
||||
|
||||
if ((wc.getEmail() == null) || (wc.getEmail().length() < 3)) {
|
||||
errors.rejectValue("email", "not-used", null, "Email is required.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
lib
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
|
||||
<!--
|
||||
- Application context definition for "contacts" DispatcherServlet.
|
||||
- $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- ========================== WEB DEFINITIONS ======================= -->
|
||||
|
||||
<bean id="publicIndexController" class="sample.contact.PublicIndexController">
|
||||
<property name="contactManager"><ref bean="contactManager"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="secureIndexController" class="sample.contact.SecureIndexController">
|
||||
<property name="contactManager"><ref bean="contactManager"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="secureDeleteController" class="sample.contact.DeleteController">
|
||||
<property name="contactManager"><ref bean="contactManager"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
|
||||
<property name="mappings">
|
||||
<props>
|
||||
<prop key="/hello.htm">publicIndexController</prop>
|
||||
<prop key="/secure/add.htm">secureAddForm</prop>
|
||||
<prop key="/secure/index.htm">secureIndexController</prop>
|
||||
<prop key="/secure/del.htm">secureDeleteController</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="addValidator" class="sample.contact.WebContactValidator"/>
|
||||
<bean id="secureAddForm" class="sample.contact.WebContactAddController">
|
||||
<property name="sessionForm"><value>true</value></property>
|
||||
<property name="commandName"><value>webContact</value></property>
|
||||
<property name="commandClass"><value>sample.contact.WebContact</value></property>
|
||||
<property name="validator"><ref bean="addValidator"/></property>
|
||||
<property name="formView"><value>add</value></property>
|
||||
<property name="successView"><value>index.htm</value></property>
|
||||
<property name="contactManager">
|
||||
<ref bean="contactManager"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
|
||||
<property name="prefix"><value>/WEB-INF/jsp/</value></property>
|
||||
<property name="suffix"><value>.jsp</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- =================== SECURITY SYSTEM DEFINITIONS ================== -->
|
||||
|
||||
<!-- RunAsManager -->
|
||||
<bean id="runAsManager" class="net.sf.acegisecurity.runas.RunAsManagerImpl">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHENTICATION DEFINITIONS ~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- We rely on the Because the web container to authenticate the user -->
|
||||
|
||||
<!-- Authentication provider that accepts as valid our RunAsManagerImpl created tokens -->
|
||||
<bean id="runAsAuthenticationProvider" class="net.sf.acegisecurity.runas.RunAsImplAuthenticationProvider">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- Authentication provider that accepts as valid any adapter-created Authentication token -->
|
||||
<bean id="authByAdapterProvider" class="net.sf.acegisecurity.adapters.AuthByAdapterProvider">
|
||||
<property name="key"><value>my_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- The authentication manager that iterates through our authentication providers -->
|
||||
<bean id="providerManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref bean="runAsAuthenticationProvider"/>
|
||||
<ref bean="authByAdapterProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- An access decision voter that reads ROLE_* configuaration settings -->
|
||||
<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
|
||||
|
||||
<!-- An access decision voter that reads CONTACT_OWNED_BY_CURRENT_USER configuaration settings -->
|
||||
<bean id="contactSecurityVoter" class="sample.contact.ContactSecurityVoter"/>
|
||||
|
||||
<!-- An affirmative access decision manager -->
|
||||
<bean id="affirmativeBased" class="net.sf.acegisecurity.vote.AffirmativeBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref bean="roleVoter"/>
|
||||
<ref bean="contactSecurityVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ===================== SECURITY DEFINITIONS ======================= -->
|
||||
|
||||
<bean id="publicContactManagerSecurity" class="net.sf.acegisecurity.SecurityInterceptor">
|
||||
<property name="authenticationManager"><ref bean="providerManager"/></property>
|
||||
<property name="accessDecisionManager"><ref bean="affirmativeBased"/></property>
|
||||
<property name="runAsManager"><ref bean="runAsManager"/></property>
|
||||
<property name="methodDefinitionSource">
|
||||
<value>
|
||||
sample.contact.ContactManager.delete=ROLE_SUPERVISOR,RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getAllByOwner=CONTACT_OWNED_BY_CURRENT_USER,RUN_AS_SERVER
|
||||
sample.contact.ContactManager.save=CONTACT_OWNED_BY_CURRENT_USER,RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getById=ROLE_TELLER,RUN_AS_SERVER
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- We expect all callers of the backend object to hold the role ROLE_RUN_AS_SERVER -->
|
||||
<bean id="backendContactManagerSecurity" class="net.sf.acegisecurity.SecurityInterceptor">
|
||||
<property name="authenticationManager"><ref bean="providerManager"/></property>
|
||||
<property name="accessDecisionManager"><ref bean="affirmativeBased"/></property>
|
||||
<property name="runAsManager"><ref bean="runAsManager"/></property>
|
||||
<property name="methodDefinitionSource">
|
||||
<value>
|
||||
sample.contact.ContactManager.delete=ROLE_RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getAllByOwner=ROLE_RUN_AS_SERVER
|
||||
sample.contact.ContactManager.save=ROLE_RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getById=ROLE_RUN_AS_SERVER
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ======================= BUSINESS DEFINITIONS ===================== -->
|
||||
|
||||
<bean id="contactManager" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>sample.contact.ContactManager</value></property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>publicContactManagerSecurity</value>
|
||||
<value>publicContactManagerTarget</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="publicContactManagerTarget" class="sample.contact.ContactManagerFacade">
|
||||
<property name="backend"><ref bean="backendContactManager"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="backendContactManager" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>sample.contact.ContactManager</value></property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>backendContactManagerSecurity</value>
|
||||
<value>backendContactManagerTarget</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="backendContactManagerTarget" class="sample.contact.ContactManagerBackend"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,6 @@
|
||||
<!--
|
||||
- $Id$
|
||||
-->
|
||||
<jboss-web>
|
||||
<security-domain>java:/jaas/SpringPoweredRealm</security-domain>
|
||||
</jboss-web>
|
||||
@@ -0,0 +1,40 @@
|
||||
<%@ include file="/WEB-INF/jsp/include.jsp" %>
|
||||
<html>
|
||||
<head><title>Add New Contact</title></head>
|
||||
<body>
|
||||
<h1>Add Contact</h1>
|
||||
<form method="post">
|
||||
<table width="95%" bgcolor="f8f8ff" border="0" cellspacing="0" cellpadding="5">
|
||||
<tr>
|
||||
<td alignment="right" width="20%">Name:</td>
|
||||
<spring:bind path="webContact.name">
|
||||
<td width="20%">
|
||||
<input type="text" name="name" value="<c:out value="${status.value}"/>">
|
||||
</td>
|
||||
<td width="60%">
|
||||
<font color="red"><c:out value="${status.errorMessage}"/></font>
|
||||
</td>
|
||||
</spring:bind>
|
||||
</tr>
|
||||
<tr>
|
||||
<td alignment="right" width="20%">Email:</td>
|
||||
<spring:bind path="webContact.email">
|
||||
<td width="20%">
|
||||
<input type="text" name="email" value="<c:out value="${status.value}"/>">
|
||||
</td>
|
||||
<td width="60%">
|
||||
<font color="red"><c:out value="${status.errorMessage}"/></font>
|
||||
</td>
|
||||
</spring:bind>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<spring:hasBindErrors name="webContact">
|
||||
<b>Please fix all errors!</b>
|
||||
</spring:hasBindErrors>
|
||||
<br><br>
|
||||
<input name="execute" type="submit" alignment="center" value="Execute">
|
||||
</form>
|
||||
<a href="<c:url value="hello.htm"/>">Home</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,13 @@
|
||||
<%@ include file="/WEB-INF/jsp/include.jsp" %>
|
||||
|
||||
<html>
|
||||
<head><title>Deletion completed</title></head>
|
||||
<body>
|
||||
<h1>Deleted</h1>
|
||||
<P>
|
||||
<code>
|
||||
<c:out value="${contact}"/>
|
||||
</code>
|
||||
<p><A HREF="index.htm">Manage</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,24 @@
|
||||
<%@ include file="/WEB-INF/jsp/include.jsp" %>
|
||||
|
||||
<html>
|
||||
<head><title>Contacts Security Demo</title></head>
|
||||
<body>
|
||||
<h1>Contacts Security Demo</h1>
|
||||
<p>This is a very simple application to demonstrate the Acegi Security System for Spring.
|
||||
The application manages contacts, partitioned based on the user that owns them.
|
||||
Users may only manage their own contacts, and only users with ROLE_SUPERVISOR
|
||||
are allowed to delete their contacts. The application automatically extracts
|
||||
the principal from the web container (which should be configured with a
|
||||
suitable Acegi Security System for Spring adapter). It also demonstrates how to configure
|
||||
server-side secure objects so they can only be accessed via a public facade.
|
||||
|
||||
<P>This application also demonstrates a public method, which is used to select
|
||||
the random contact that is shown below:
|
||||
<P>
|
||||
<code>
|
||||
<c:out value="${contact}"/>
|
||||
</code>
|
||||
<p>
|
||||
<p><A HREF="secure/index.htm">Manage</a> <A HREF="secure/debug.jsp">Debug</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,4 @@
|
||||
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
|
||||
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
|
||||
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>
|
||||
@@ -0,0 +1,29 @@
|
||||
<%@ include file="/WEB-INF/jsp/include.jsp" %>
|
||||
|
||||
<html>
|
||||
<head><title>Your Contacts</title></head>
|
||||
<body>
|
||||
<h1><c:out value="${model.user}"/>'s Contacts</h1>
|
||||
<P>
|
||||
<table cellpadding=3 border=0>
|
||||
<tr><td><b>id</b></td><td><b>Name</b></td><td><b>Email</b></td></tr>
|
||||
<c:forEach var="contact" items="${model.contacts}">
|
||||
<tr>
|
||||
<td>
|
||||
<c:out value="${contact.id}"/>
|
||||
</td>
|
||||
<td>
|
||||
<c:out value="${contact.name}"/>
|
||||
</td>
|
||||
<td>
|
||||
<c:out value="${contact.email}"/>
|
||||
</td>
|
||||
<c:if test="${model.supervisor == true}">
|
||||
<td><A HREF="del.htm?id=<c:out value="${contact.id}"/>">Del</A></td>
|
||||
</c:if>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
</table>
|
||||
<p><A HREF="add.htm">Add</a> <A HREF="../logoff.jsp">Logoff</A>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,46 @@
|
||||
<?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$
|
||||
-->
|
||||
|
||||
<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>
|
||||
@@ -0,0 +1,12 @@
|
||||
<!--
|
||||
- $Id$
|
||||
-->
|
||||
<web-app>
|
||||
<authenticator>
|
||||
<type>net.sf.acegisecurity.adapters.resin.ResinSpringAuthenticator</type>
|
||||
<init>
|
||||
<app-context-location>WEB-INF/resin-acegisecurity.xml</app-context-location>
|
||||
<key>my_password</key>
|
||||
</init>
|
||||
</authenticator>
|
||||
</web-app>
|
||||
@@ -0,0 +1,193 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
|
||||
|
||||
<taglib>
|
||||
|
||||
<tlib-version>1.0</tlib-version>
|
||||
|
||||
<jsp-version>1.2</jsp-version>
|
||||
|
||||
<short-name>Spring</short-name>
|
||||
|
||||
<uri>http://www.springframework.org/tags</uri>
|
||||
|
||||
<description>Spring Framework JSP Tag Library. Authors: Rod Johnson, Juergen Hoeller</description>
|
||||
|
||||
<tag>
|
||||
|
||||
<name>htmlEscape</name>
|
||||
<tag-class>org.springframework.web.servlet.tags.HtmlEscapeTag</tag-class>
|
||||
<body-content>JSP</body-content>
|
||||
|
||||
<description>
|
||||
Sets default HTML escape value for the current page.
|
||||
</description>
|
||||
|
||||
<attribute>
|
||||
<name>defaultHtmlEscape</name>
|
||||
<required>true</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
||||
<name>message</name>
|
||||
<tag-class>org.springframework.web.servlet.tags.MessageTag</tag-class>
|
||||
<body-content>JSP</body-content>
|
||||
|
||||
<description>
|
||||
Retrieves the message with the given code, or text if code isn't resolvable.
|
||||
</description>
|
||||
|
||||
<attribute>
|
||||
<name>code</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>text</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>htmlEscape</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
||||
<name>theme</name>
|
||||
<tag-class>org.springframework.web.servlet.tags.ThemeTag</tag-class>
|
||||
<body-content>JSP</body-content>
|
||||
|
||||
<description>
|
||||
Retrieves the theme message with the given code, or text if code isn't resolvable.
|
||||
</description>
|
||||
|
||||
<attribute>
|
||||
<name>code</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>text</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>htmlEscape</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
||||
<name>hasBindErrors</name>
|
||||
<tag-class>org.springframework.web.servlet.tags.BindErrorsTag</tag-class>
|
||||
<body-content>JSP</body-content>
|
||||
|
||||
<description>
|
||||
Provides Errors instance in case of bind errors.
|
||||
</description>
|
||||
|
||||
<!-- Note: Was "Integer count" in earlier version -->
|
||||
<variable>
|
||||
<name-given>errors</name-given>
|
||||
<variable-class>org.springframework.validation.Errors</variable-class>
|
||||
</variable>
|
||||
|
||||
<!-- Note: Now one Errors instance per bind object -> name of object needed -->
|
||||
<attribute>
|
||||
<name>name</name>
|
||||
<required>true</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>htmlEscape</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
||||
<name>bind</name>
|
||||
<tag-class>org.springframework.web.servlet.tags.BindTag</tag-class>
|
||||
<body-content>JSP</body-content>
|
||||
|
||||
<description>
|
||||
Provides BindStatus instance for certain bind path.
|
||||
</description>
|
||||
|
||||
<!-- Note: Was "bind" in earlier version -->
|
||||
<variable>
|
||||
<name-given>status</name-given>
|
||||
<variable-class>org.springframework.web.servlet.tags.BindStatus</variable-class>
|
||||
</variable>
|
||||
|
||||
<!-- Note: Was "value" in earlier version -->
|
||||
<attribute>
|
||||
<name>path</name>
|
||||
<required>true</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>htmlEscape</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
||||
<name>transform</name>
|
||||
<tag-class>org.springframework.web.servlet.tags.TransformTag</tag-class>
|
||||
<body-content>JSP</body-content>
|
||||
|
||||
<description>
|
||||
Provides transformation of variables to Strings using appropriate
|
||||
Custom Editor from BindTag (can only be used inside BindTag)
|
||||
</description>
|
||||
|
||||
<attribute>
|
||||
<name>value</name>
|
||||
<required>true</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>var</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>scope</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>htmlEscape</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
</tag>
|
||||
|
||||
</taglib>
|
||||
@@ -0,0 +1,100 @@
|
||||
<?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$
|
||||
-->
|
||||
|
||||
<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</filter-name>
|
||||
<filter-class>net.sf.acegisecurity.adapters.AutoIntegrationFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>Acegi Security System for Spring</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>
|
||||
<!-- Define the context-relative URL(s) to be protected -->
|
||||
<url-pattern>/secure/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<!-- Anyone with one of the listed roles may access this area -->
|
||||
<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>
|
||||
@@ -0,0 +1,4 @@
|
||||
<%@ include file="/WEB-INF/jsp/include.jsp" %>
|
||||
|
||||
<%-- Redirected because we can't set the welcome page to a virtual URL. --%>
|
||||
<c:redirect url="/hello.htm"/>
|
||||
@@ -0,0 +1,43 @@
|
||||
<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %>
|
||||
|
||||
<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>
|
||||
@@ -0,0 +1,3 @@
|
||||
<%session.invalidate();
|
||||
response.sendRedirect("index.jsp");
|
||||
%>
|
||||
@@ -0,0 +1,48 @@
|
||||
<%@ page import="net.sf.acegisecurity.context.Context" %>
|
||||
<%@ page import="net.sf.acegisecurity.context.ContextHolder" %>
|
||||
<%@ page import="net.sf.acegisecurity.context.SecureContext" %>
|
||||
<%@ page import="net.sf.acegisecurity.Authentication" %>
|
||||
<%@ page import="net.sf.acegisecurity.GrantedAuthority" %>
|
||||
<%@ page import="net.sf.acegisecurity.adapters.AuthByAdapter" %>
|
||||
|
||||
<% Context context = ContextHolder.getContext();
|
||||
if (context != null) { %>
|
||||
Context on ContextHolder is of type: <%= context.getClass().getName() %><BR><BR>
|
||||
|
||||
<% if (context instanceof SecureContext) { %>
|
||||
The Context implements SecureContext.<BR><BR>
|
||||
<% SecureContext sc = (SecureContext) context;
|
||||
|
||||
Authentication auth = sc.getAuthentication();
|
||||
if (auth != null) { %>
|
||||
Authentication object is of type: <%= auth.getClass().getName() %><BR><BR>
|
||||
Authentication object as a String: <%= auth.toString() %><BR><BR>
|
||||
|
||||
Authentication object holds the following granted authorities:<BR><BR>
|
||||
<% GrantedAuthority[] granted = auth.getAuthorities();
|
||||
for (int i = 0; i < granted.length; i++) { %>
|
||||
<%= granted[i].toString() %> (getAuthority(): <%= granted[i].getAuthority() %>)<BR>
|
||||
<% }
|
||||
|
||||
if (auth instanceof AuthByAdapter) { %>
|
||||
<BR><B>SUCCESS! Your container adapter appears to be properly configured!</B><BR><BR>
|
||||
<% } else { %>
|
||||
<BR><I>WARNING: Authentication object does not implement AuthByAdapter</I><BR>
|
||||
This may point to an error with your adapter configuration, although can be ignored if intentional.<BR><BR>
|
||||
<% }
|
||||
|
||||
} else { %>
|
||||
Authentication object is null.<BR>
|
||||
This is an error and your container adapter will not operate properly until corrected.<BR><BR>
|
||||
<% }
|
||||
} else { %>
|
||||
<B>ContextHolder does not contain a SecureContext.</B><BR>
|
||||
This is an error and your container adapter will not operate properly until corrected.<BR><BR>
|
||||
<% }
|
||||
} else { %>
|
||||
<B>ContextHolder on ContextHolder is null.</B><BR>
|
||||
This indicates improper setup of the container adapter. Refer to the reference documentation.<BR>
|
||||
Also ensure the correct subclass of AbstractMvcIntegrationInterceptor is being used for your container.<BR>
|
||||
<%}
|
||||
%>
|
||||
|
||||
Reference in New Issue
Block a user