2004-04-03 05:37:20 +00:00
|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
|
|
|
|
|
"../lib/docbook-dtd/docbookx.dtd">
|
|
|
|
|
<book>
|
|
|
|
|
<bookinfo>
|
|
|
|
|
<title>Acegi Security System for Spring</title>
|
|
|
|
|
|
|
|
|
|
<subtitle>Reference Documentation</subtitle>
|
|
|
|
|
|
2004-04-09 05:41:42 +00:00
|
|
|
|
<releaseinfo>0.5</releaseinfo>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<authorgroup>
|
|
|
|
|
<author>
|
|
|
|
|
<firstname>Ben</firstname>
|
|
|
|
|
|
|
|
|
|
<surname>Alex</surname>
|
|
|
|
|
</author>
|
|
|
|
|
</authorgroup>
|
|
|
|
|
</bookinfo>
|
|
|
|
|
|
|
|
|
|
<toc></toc>
|
|
|
|
|
|
|
|
|
|
<preface id="preface">
|
|
|
|
|
<title>Preface</title>
|
|
|
|
|
|
|
|
|
|
<para>This document provides a reference guide to the Acegi Security
|
|
|
|
|
System for Spring, which is a series of classes that deliver
|
|
|
|
|
authentication and authorization services within the Spring Framework.
|
|
|
|
|
Whilst the Acegi Security System for Spring is not officially part of
|
|
|
|
|
Spring, it is hoped this implementation will further discussion concerning
|
|
|
|
|
the implementation of security capabilities within Spring itself.</para>
|
|
|
|
|
|
|
|
|
|
<para>I would like to acknowledge this reference was prepared using the
|
|
|
|
|
DocBook configuration included with the Spring Framework. The Spring team
|
|
|
|
|
in turn acknowledge Chris Bauer (Hibernate) for his assistance with their
|
|
|
|
|
DocBook.</para>
|
|
|
|
|
</preface>
|
|
|
|
|
|
|
|
|
|
<chapter id="security">
|
|
|
|
|
<title>Security</title>
|
|
|
|
|
|
|
|
|
|
<sect1 id="security-introduction">
|
|
|
|
|
<title>Introduction</title>
|
|
|
|
|
|
|
|
|
|
<para>The Acegi Security System for Spring provides authentication and
|
|
|
|
|
authorization capabilities for Spring-powered projects, with full
|
|
|
|
|
integration with popular web containers. The security architecture was
|
|
|
|
|
designed from the ground up using "The Spring Way" of development, which
|
|
|
|
|
includes using bean contexts, interceptors and interface-driven
|
|
|
|
|
programming. As a consequence, the Acegi Security System for Spring is
|
|
|
|
|
useful out-of-the-box for those seeking to secure their Spring-based
|
|
|
|
|
applications, and can be easily adapted to complex customized
|
|
|
|
|
requirements.</para>
|
|
|
|
|
|
|
|
|
|
<para>Security involves two distinct operations, authentication and
|
|
|
|
|
authorization. The former relates to resolving whether or not a caller
|
|
|
|
|
is who they claim to be. Authorization on the other hand relates to
|
|
|
|
|
determining whether or not an authenticated caller is permitted to
|
|
|
|
|
perform a given operation.</para>
|
|
|
|
|
|
|
|
|
|
<para>Throughout the Acegi Security System for Spring, the user, system
|
|
|
|
|
or agent that needs to be authenticated is referred to as a "principal".
|
|
|
|
|
The security architecture does not have a notion of roles or groups,
|
|
|
|
|
which you may be familiar with from other security
|
|
|
|
|
implementations.</para>
|
|
|
|
|
</sect1>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect1 id="security-high-level-design">
|
|
|
|
|
<title>High Level Design</title>
|
|
|
|
|
|
|
|
|
|
<sect2 id="security-high-level-design-key-components">
|
|
|
|
|
<title>Key Components</title>
|
|
|
|
|
|
|
|
|
|
<para>The Acegi Security System for Spring essentially comprises six
|
|
|
|
|
key functional parts:</para>
|
|
|
|
|
|
|
|
|
|
<itemizedlist spacing="compact">
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>An <literal>Authentication</literal> object which holds the
|
|
|
|
|
principal, credentials and the authorities granted to the
|
|
|
|
|
principal.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>A <literal>ContextHolder</literal> which holds the
|
|
|
|
|
<literal>Authentication</literal> object in a
|
|
|
|
|
<literal>ThreadLocal</literal>-bound object.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>An <literal>AuthenticationManager</literal> to authenticate
|
|
|
|
|
the <literal>Authentication</literal> object presented via the
|
|
|
|
|
<literal>ContextHolder</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>An <literal>AccessDecisionManager</literal> to authorize a
|
|
|
|
|
given operation.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>A <literal>RunAsManager</literal> to optionally replace the
|
|
|
|
|
<literal>Authentication</literal> object whilst a given operation
|
|
|
|
|
is being executed.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>A "secure object" interceptor, which coordinates the
|
|
|
|
|
authentication, authorization, run-as replacement and execution of
|
|
|
|
|
a given operation.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
</itemizedlist>
|
|
|
|
|
|
|
|
|
|
<para>Secure objects refer to any type of object that can have
|
|
|
|
|
security applied to it. A secure object must provide some form of
|
|
|
|
|
callback, so that the security interceptor can transparently do its
|
|
|
|
|
work as required, and callback the object when it is time for it to
|
|
|
|
|
proceed with the requested operation. If secure objects cannot provide
|
|
|
|
|
a native callback approach, a wrapper needs to be written so this
|
|
|
|
|
becomes possible.</para>
|
|
|
|
|
|
|
|
|
|
<para>Each secure object has its own package under
|
|
|
|
|
<literal>net.sf.acegisecurity.intercept</literal>. Every other package
|
|
|
|
|
in the security system is secure object independent, in that it can
|
|
|
|
|
support any type of secure object presented.</para>
|
|
|
|
|
|
|
|
|
|
<para>Only developers contemplating an entirely new way of
|
|
|
|
|
intercepting and authorizing requests would need to use secure objects
|
|
|
|
|
directly. For example, it would be possible to build a new secure
|
|
|
|
|
object to secure calls to a messaging system that does not use
|
|
|
|
|
<literal>MethodInvocation</literal>s. Most Spring applications will
|
|
|
|
|
simply use the two currently supported secure object types
|
|
|
|
|
(<literal>MethodInvocation</literal> and
|
|
|
|
|
<literal>FilterInterceptor</literal>) with complete
|
|
|
|
|
transparency.</para>
|
|
|
|
|
|
|
|
|
|
<para>Each of the six key parts is discussed in detail throughout this
|
|
|
|
|
document.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
|
|
<sect2 id="security-high-level-design-supported-secure-objects">
|
|
|
|
|
<title>Supported Secure Objects</title>
|
|
|
|
|
|
|
|
|
|
<para>The Acegi Security System for Spring currently supports two
|
|
|
|
|
secure objects.</para>
|
|
|
|
|
|
|
|
|
|
<para>The first handles an AOP Alliance
|
|
|
|
|
<literal>MethodInvocation</literal>. This is the secure object type
|
|
|
|
|
used to protect Spring beans. Developers will generally use this
|
|
|
|
|
secure object type to secure their business objects. To make a
|
|
|
|
|
standard Spring-hosted bean available as a
|
|
|
|
|
<literal>MethodInvocation</literal>, the bean is simply published
|
|
|
|
|
through a <literal>ProxyFactoryBean</literal> or
|
|
|
|
|
<literal>BeanNameAutoProxyCreator</literal>. Most Spring developers
|
|
|
|
|
would already be familiar with these due to their use in transactions
|
|
|
|
|
and other areas of Spring.</para>
|
|
|
|
|
|
|
|
|
|
<para>The second type is a <literal>FilterInvocation</literal>. This
|
|
|
|
|
is an object included with the Acegi Security System for Spring. It is
|
|
|
|
|
created by an included filter and simply wraps the HTTP
|
|
|
|
|
<literal>ServletRequest</literal>, <literal>ServletResponse</literal>
|
|
|
|
|
and <literal>FilterChain</literal>. The
|
|
|
|
|
<literal>FilterInvocation</literal> enables HTTP resources to be
|
|
|
|
|
secured. Developers do not usually need to understand the mechanics of
|
|
|
|
|
how this works, because they just add the filters to their
|
|
|
|
|
<literal>web.xml</literal> and let the security system do its
|
|
|
|
|
work.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
|
|
<sect2 id="security-high-level-design-configuration-attributes">
|
|
|
|
|
<title>Configuration Attributes</title>
|
|
|
|
|
|
|
|
|
|
<para>Every secure object can represent an infinite number of
|
|
|
|
|
individual requests. For example, a
|
|
|
|
|
<literal>MethodInvocation</literal> can represent the invocation of
|
|
|
|
|
any method with any arguments, whilst a
|
|
|
|
|
<literal>FilterInvocation</literal> can represent any HTTP URL.</para>
|
|
|
|
|
|
|
|
|
|
<para>The Acegi Security System for Spring needs to record the
|
|
|
|
|
configuration that applies to each of these possible requests. The
|
|
|
|
|
security configuration of a request to
|
|
|
|
|
<literal>BankManager.getBalance(int accountNumber)</literal> needs to
|
|
|
|
|
be very different from the security configuration of a request to
|
|
|
|
|
<literal>BankManager.approveLoan(int applicationNumber)</literal>.
|
|
|
|
|
Similarly, the security configuration of a request to
|
|
|
|
|
<literal>http://some.bank.com/index.htm</literal> needs to be very
|
|
|
|
|
different from the security configuration of
|
|
|
|
|
<literal>http://some.bank.com/manage/timesheet.jsp</literal>.</para>
|
|
|
|
|
|
|
|
|
|
<para>To store the various security configurations associated with
|
|
|
|
|
different requests, a configuration attribute is used. At an
|
|
|
|
|
implementation level a configuration attribute is represented by the
|
|
|
|
|
<literal>ConfigAttribute</literal> interface. One concrete
|
|
|
|
|
implementation of <literal>ConfigAttribute</literal> is provided,
|
|
|
|
|
<literal>SecurityConfig</literal>, which simply stores a configuration
|
|
|
|
|
attribute as a <literal>String</literal>.</para>
|
|
|
|
|
|
|
|
|
|
<para>The collection of <literal>ConfigAttribute</literal>s associated
|
|
|
|
|
with a particular request is held in a
|
|
|
|
|
<literal>ConfigAttributeDefinition</literal>. This concrete class is
|
|
|
|
|
simply a holder of <literal>ConfigAttribute</literal>s and does
|
|
|
|
|
nothing special.</para>
|
|
|
|
|
|
|
|
|
|
<para>When a request is received by the security interceptor, it needs
|
|
|
|
|
to determine which configuration attributes apply. In other words, it
|
|
|
|
|
needs to find the <literal>ConfigAttributeDefinition</literal> which
|
|
|
|
|
applies to the request. This decision is handled by the
|
|
|
|
|
<literal>ObjectDefinitionSource</literal> interface. The main method
|
|
|
|
|
provided by this interface is <literal>public
|
|
|
|
|
ConfigAttributeDefinition getAttributes(Object object)</literal>, with
|
|
|
|
|
the <literal>Object</literal> being the secure object. Recall the
|
|
|
|
|
secure object contains details of the request, so the
|
|
|
|
|
<literal>ObjectDefinitionSource</literal> implementation will be able
|
|
|
|
|
to extract the details it requires to lookup the relevant
|
|
|
|
|
<literal>ConfigAttributeDefinition</literal>.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
</sect1>
|
|
|
|
|
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<sect1 id="security-request-contexts">
|
|
|
|
|
<title>Request Contexts</title>
|
|
|
|
|
|
|
|
|
|
<sect2 id="security-contexts">
|
|
|
|
|
<title>Contexts</title>
|
|
|
|
|
|
|
|
|
|
<para>Many applications require a way of sharing objects between
|
|
|
|
|
classes, but without resorting to passing them in method signatures.
|
|
|
|
|
This is commonly achieved by using a <literal>ThreadLocal</literal>.
|
|
|
|
|
The Acegi Security System for Spring uses
|
|
|
|
|
<literal>ThreadLocal</literal> functionality and introduces the
|
|
|
|
|
concept of "request contexts".</para>
|
|
|
|
|
|
|
|
|
|
<para>By placing an object into a request context, that object becomes
|
|
|
|
|
available to any other object on the current thread of execution. The
|
|
|
|
|
request context is not passed around as a method parameter, but is
|
|
|
|
|
held in a <literal>ThreadLocal</literal>. The Acegi Security System
|
|
|
|
|
for Spring uses the request context to pass around the authentication
|
|
|
|
|
request and response.</para>
|
|
|
|
|
|
|
|
|
|
<para>A request context is a concrete implementation of the
|
|
|
|
|
<literal>Context</literal> interface, which exposes a single
|
|
|
|
|
method:</para>
|
|
|
|
|
|
|
|
|
|
<programlisting>public void validate() throws ContextInvalidException;</programlisting>
|
|
|
|
|
|
|
|
|
|
<para>This <literal>validate()</literal> method is called to confirm
|
|
|
|
|
the <literal>Context</literal> is properly setup. An implementation
|
|
|
|
|
will typically use this method to check that the objects it holds are
|
|
|
|
|
properly setup.</para>
|
|
|
|
|
|
|
|
|
|
<para>The <literal>ContextHolder</literal> class makes the
|
|
|
|
|
<literal>Context</literal> available to the current thread of
|
|
|
|
|
execution using a <literal>ThreadLocal</literal>. A
|
|
|
|
|
<literal>ContextInterceptor</literal> is also provided, which is
|
|
|
|
|
intended to be chained into the bean context using
|
|
|
|
|
<literal>ProxyFactoryBean</literal>. The
|
|
|
|
|
<literal>ContextInterceptor</literal> simply calls
|
|
|
|
|
<literal>Context.validate()</literal>, which guarantees to business
|
|
|
|
|
methods that a valid <literal>Context</literal> is available from the
|
|
|
|
|
<literal>ContextHolder</literal>.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
|
|
<sect2 id="security-contexts-secure-contexts">
|
|
|
|
|
<title>Secure Contexts</title>
|
|
|
|
|
|
|
|
|
|
<para>The Acegi Security System for Spring requires the
|
|
|
|
|
<literal>ContextHolder</literal> to contain a request context that
|
|
|
|
|
implements the <literal>SecureContext</literal> interface. An
|
|
|
|
|
implementation is provided named <literal>SecureContextImpl</literal>.
|
|
|
|
|
The <literal>SecureContext</literal> simply extends the
|
|
|
|
|
<literal>Context</literal> discussed above and adds a holder and
|
|
|
|
|
validation for an <literal>Authentication</literal> object.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
|
|
<sect2 id="security-contexts-custom-contexts">
|
|
|
|
|
<title>Custom Contexts</title>
|
|
|
|
|
|
|
|
|
|
<para>Developers can create their own request context classes to store
|
|
|
|
|
application-specific objects. Such request context classes will need
|
|
|
|
|
to implement the <literal>Context</literal> interface. If the Acegi
|
|
|
|
|
Security System for Spring is to be used, developers must ensure any
|
|
|
|
|
custom request contexts implement the <literal>SecureContext</literal>
|
|
|
|
|
interface.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
|
|
<sect1 id="security-interception">
|
|
|
|
|
<title>Security Interception</title>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-interception-all-secure-objects">
|
|
|
|
|
<title>All Secure Objects</title>
|
|
|
|
|
|
|
|
|
|
<para>As described in the High Level Design section, each secure
|
|
|
|
|
object has its own security interceptor which is responsible for
|
|
|
|
|
handling each request. Handling involves a number of
|
|
|
|
|
operations:</para>
|
|
|
|
|
|
|
|
|
|
<itemizedlist spacing="compact">
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Store the configuration attributes that are associated with
|
|
|
|
|
each secure request.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Extract the <literal>ConfigAttributeDefinition</literal>
|
|
|
|
|
that applies to the request from the relevant
|
|
|
|
|
<literal>ObjectDefinitionSource</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Obtain the <literal>Authentication</literal> object from the
|
|
|
|
|
<literal>SecureContext</literal>, which is held in the
|
|
|
|
|
<literal>ContextHolder</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Pass the <literal>Authentication</literal> object to the
|
|
|
|
|
<literal>AuthenticationManager</literal>, update the
|
|
|
|
|
<literal>ContextHolder</literal> with the response.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Pass the <literal>Authentication</literal> object, the
|
|
|
|
|
<literal>ConfigAttributeDefinition</literal>, and the secure
|
|
|
|
|
object to the <literal>AccessDecisionManager</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Pass the <literal>Authentication</literal> object, the
|
|
|
|
|
<literal>ConfigAttributeDefinition</literal>, and the secure
|
|
|
|
|
object to the <literal>RunAsManager</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>If the <literal>RunAsManager</literal> returns a new
|
|
|
|
|
<literal>Authentication</literal> object, update the
|
|
|
|
|
<literal>ContextHolder</literal> with it.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Call a secure object-specific
|
|
|
|
|
<literal>SecurityInterceptorCallback</literal> so that the request
|
|
|
|
|
execution can proceed.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>If the <literal>RunAsManager</literal> earlier returned a
|
|
|
|
|
new <literal>Authentication</literal> object, update the
|
|
|
|
|
<literal>ContextHolder</literal> with the
|
|
|
|
|
<literal>Authentication</literal> object that was previously
|
|
|
|
|
returned by the <literal>AuthenticationManager</literal>.</para>
|
|
|
|
|
</listitem>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<listitem>
|
|
|
|
|
<para>Return any result received from the
|
|
|
|
|
<literal>SecurityInterceptorCallback</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
</itemizedlist>
|
|
|
|
|
|
|
|
|
|
<para>Whilst this may seem quite involved, don't worry. Developers
|
|
|
|
|
interact with the security process by simply implementing basic
|
|
|
|
|
interfaces (such as <literal>AccessDecisionManager</literal>), which
|
2004-04-09 05:41:42 +00:00
|
|
|
|
are fully documented below.</para>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
|
|
|
|
|
<para>The <literal>AbstractSecurityInterceptor</literal> handles the
|
|
|
|
|
majority of the flow listed above. Each secure object has its own
|
|
|
|
|
security interceptor which subclasses
|
|
|
|
|
<literal>AbstractSecurityInterceptor</literal>. Each of these secure
|
|
|
|
|
object-specific security interceptors are discussed below.</para>
|
|
|
|
|
</sect2>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-interception-methodinvocation">
|
|
|
|
|
<title>MethodInvocation Security Interceptor</title>
|
|
|
|
|
|
|
|
|
|
<para>To secure <literal>MethodInvocation</literal>s, developers
|
|
|
|
|
simply add a properly configured
|
|
|
|
|
<literal>MethodSecurityInterceptor</literal> into the application
|
|
|
|
|
context. Next the beans requiring security are chained into the
|
|
|
|
|
interceptor. This chaining is accomplished using Spring’s
|
|
|
|
|
<literal>ProxyFactoryBean</literal> or
|
|
|
|
|
<literal>BeanNameAutoProxyCreator</literal>, as commonly used by many
|
|
|
|
|
other parts of Spring (refer to the sample application for examples).
|
|
|
|
|
The <literal>MethodSecurityInterceptor</literal> is configured as
|
|
|
|
|
follows:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting><bean id="bankManagerSecurity" class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<property name="validateConfigAttributes"><value>true</value></property>
|
|
|
|
|
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
|
|
|
|
<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
|
|
|
|
|
<property name="runAsManager"><ref bean="runAsManager"/></property>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<property name="objectDefinitionSource">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<value>
|
|
|
|
|
net.sf.acegisecurity.context.BankManager.delete*=ROLE_SUPERVISOR,RUN_AS_SERVER
|
|
|
|
|
net.sf.acegisecurity.context.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER,RUN_AS_SERVER
|
|
|
|
|
</value>
|
|
|
|
|
</property>
|
|
|
|
|
</bean></programlisting></para>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>As shown above, the <literal>MethodSecurityInterceptor</literal>
|
|
|
|
|
is configured with a reference to an
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>AuthenticationManager</literal>,
|
|
|
|
|
<literal>AccessDecisionManager</literal> and
|
|
|
|
|
<literal>RunAsManager</literal>, which are each discussed in separate
|
2004-04-03 05:37:20 +00:00
|
|
|
|
sections below. The <literal>MethodSecurityInterceptor</literal> is
|
|
|
|
|
also configured with configuration attributes that apply to different
|
|
|
|
|
method signatures. A full discussion of configuration attributes is
|
|
|
|
|
provided in the High Level Design section of this document.</para>
|
|
|
|
|
|
|
|
|
|
<para>The <literal>MethodSecurityInterceptor</literal> can be
|
|
|
|
|
configured with configuration attributes in three ways. The first is
|
|
|
|
|
via a property editor and the application context, which is shown
|
|
|
|
|
above. The second is via defining the configuration attributes in your
|
|
|
|
|
source code using Jakarta Commons Attributes. The third is via writing
|
|
|
|
|
your own <literal>ObjectDefinitionSource</literal>, although this is
|
|
|
|
|
beyond the scope of this document. Irrespective of the approach used,
|
|
|
|
|
the <literal>ObjectDefinitionSource</literal> is responsible for
|
|
|
|
|
returning a <literal>ConfigAttributeDefinition</literal> object that
|
|
|
|
|
contains all of the configuration attributes associated with a single
|
|
|
|
|
secure method.</para>
|
|
|
|
|
|
|
|
|
|
<para>It should be noted that the
|
|
|
|
|
<literal>MethodSecurityInterceptor.setObjectDefinitionSource()</literal>
|
|
|
|
|
method actually expects an instance of
|
|
|
|
|
<literal>MethodDefinitionSource</literal>. This is a marker interface
|
|
|
|
|
which subclasses <literal>ObjectDefinitionSource</literal>. It simply
|
|
|
|
|
denotes the <literal>ObjectDefinitionSource</literal> understands
|
|
|
|
|
<literal>MethodInvocation</literal>s. In the interests of simplicity
|
|
|
|
|
we'll continue to refer to the
|
|
|
|
|
<literal>MethodDefinitionSource</literal> as an
|
|
|
|
|
<literal>ObjectDefinitionSource</literal>, as the distinction is of
|
|
|
|
|
little relevance to most users of the
|
|
|
|
|
<literal>MethodSecurityInterceptor</literal>.</para>
|
|
|
|
|
|
|
|
|
|
<para>If using the application context property editor approach (as
|
|
|
|
|
shown above), commas are used to delimit the different configuration
|
|
|
|
|
attributes that apply to a given method pattern. Each configuration
|
|
|
|
|
attribute is assigned into its own <literal>SecurityConfig</literal>
|
|
|
|
|
object. The <literal>SecurityConfig</literal> object is discussed in
|
|
|
|
|
the High Level Design section.</para>
|
|
|
|
|
|
|
|
|
|
<para>If using the Jakarta Commons Attributes approach, your bean
|
|
|
|
|
context will be configured differently:</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<para><programlisting><bean id="attributes" class="org.springframework.metadata.commons.CommonsAttributes"/>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<bean id="objectDefinitionSource" class="net.sf.acegisecurity.intercept.method.MethodDefinitionAttributes">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<property name="attributes"><ref local="attributes"/></property>
|
|
|
|
|
</bean>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<bean id="bankManagerSecurity" class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<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>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<property name="objectDefinitionSource"><ref bean="objectDefinitionSource"/></property>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</bean></programlisting></para>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>In addition, your source code will contain Jakarta Commons
|
|
|
|
|
Attributes tags that refer to a concrete implementation of
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>ConfigAttribute</literal>. The following example uses the
|
|
|
|
|
<literal>SecurityConfig</literal> implementation to represent the
|
|
|
|
|
configuration attributes, and results in the same security
|
|
|
|
|
configuration as provided by the property editor approach
|
|
|
|
|
above:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting>public interface BankManager {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @@SecurityConfig("ROLE_SUPERVISOR")
|
|
|
|
|
* @@SecurityConfig("RUN_AS_SERVER")
|
|
|
|
|
*/
|
|
|
|
|
public void deleteSomething(int id);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @@SecurityConfig("ROLE_SUPERVISOR")
|
|
|
|
|
* @@SecurityConfig("RUN_AS_SERVER")
|
|
|
|
|
*/
|
|
|
|
|
public void deleteAnother(int id);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @@SecurityConfig("ROLE_TELLER")
|
|
|
|
|
* @@SecurityConfig("ROLE_SUPERVISOR")
|
|
|
|
|
* @@SecurityConfig("BANKSECURITY_CUSTOMER")
|
|
|
|
|
* @@SecurityConfig("RUN_AS_SERVER")
|
|
|
|
|
*/
|
|
|
|
|
public float getBalance(int id);
|
|
|
|
|
}</programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>You might have noticed the
|
|
|
|
|
<literal>validateConfigAttributes</literal> property in the above
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>MethodSecurityInterceptor</literal> examples. When set to
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>true</literal> (the default), at startup time the
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>MethodSecurityInterceptor</literal> will evaluate if the
|
|
|
|
|
provided configuration attributes are valid. It does this by checking
|
|
|
|
|
each configuration attribute can be processed by either the
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>AccessDecisionManager</literal> or the
|
|
|
|
|
<literal>RunAsManager</literal>. If neither of these can process a
|
|
|
|
|
given configuration attribute, an exception is thrown. If using the
|
2004-04-03 05:37:20 +00:00
|
|
|
|
Jakarta Commons Attributes method of configuration, you should set
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>validateConfigAttributes</literal> to
|
|
|
|
|
<literal>false</literal>.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-interception-filterinvocation">
|
|
|
|
|
<title>FilterInvocation Security Interceptor</title>
|
|
|
|
|
|
|
|
|
|
<para>To secure <literal>FilterInvocation</literal>s, developers need
|
2004-04-16 06:31:48 +00:00
|
|
|
|
to add a filter to their <literal>web.xml</literal> that delegates to
|
|
|
|
|
the <literal>SecurityEnforcementFilter</literal>. A typical
|
|
|
|
|
configuration example is provided below: <programlisting><filter>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<filter-name>Acegi HTTP Request Security Filter</filter-name>
|
2004-04-16 06:31:48 +00:00
|
|
|
|
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<init-param>
|
2004-04-16 06:31:48 +00:00
|
|
|
|
<param-name>targetClass</param-name>
|
|
|
|
|
<param-value>net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter</param-value>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
</init-param>
|
|
|
|
|
</filter>
|
|
|
|
|
|
|
|
|
|
<filter-mapping>
|
|
|
|
|
<filter-name>Acegi HTTP Request Security Filter</filter-name>
|
|
|
|
|
<url-pattern>/*</url-pattern>
|
|
|
|
|
</filter-mapping></programlisting></para>
|
|
|
|
|
|
2004-04-16 06:31:48 +00:00
|
|
|
|
<para>Notice that the filter is actually a
|
|
|
|
|
<literal>FilterToBeanProxy</literal>. Most of the filters used by the
|
|
|
|
|
Acegi Security System for Spring use this class . What it does is
|
|
|
|
|
delegate the <literal>Filter</literal>'s methods through to a bean
|
|
|
|
|
which is obtained from the Spring application context. This enables
|
|
|
|
|
the bean to benefit from the Spring application context lifecycle
|
2004-04-16 12:37:58 +00:00
|
|
|
|
support and configuration flexibility.
|
2004-04-16 06:31:48 +00:00
|
|
|
|
<literal>FilterToBeanProxy</literal> only requires a single
|
2004-04-16 12:37:58 +00:00
|
|
|
|
initialization parameter, <literal>targetClass</literal> or
|
|
|
|
|
<literal>targetBean</literal>. The <literal>targetClass</literal>
|
|
|
|
|
parameter locates the first object in the application context of the
|
|
|
|
|
specified class, whilst <literal>targetBean</literal> locates the
|
|
|
|
|
object by bean name. Like standard Spring web applications, the
|
2004-04-16 06:31:48 +00:00
|
|
|
|
<literal>FilterToBeanProxy</literal> accesses the application context
|
|
|
|
|
via<literal>
|
|
|
|
|
WebApplicationContextUtils.getWebApplicationContext(ServletContext)</literal>,
|
|
|
|
|
so you should configure a <literal>ContextLoaderListener</literal> in
|
|
|
|
|
<literal>web.xml</literal>.</para>
|
|
|
|
|
|
|
|
|
|
<para>In the application context you will need to configure two
|
|
|
|
|
beans:</para>
|
|
|
|
|
|
|
|
|
|
<programlisting><bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
|
|
|
|
|
<property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property>
|
|
|
|
|
<property name="loginFormUrl"><value>/acegilogin.jsp</value></property>
|
|
|
|
|
</bean>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
|
2004-04-16 06:31:48 +00:00
|
|
|
|
<bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor">
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<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
|
2004-04-09 09:51:23 +00:00
|
|
|
|
\A/secure/super/.*\Z=ROLE_WE_DONT_HAVE
|
2004-04-03 05:37:20 +00:00
|
|
|
|
\A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_TELLER
|
|
|
|
|
</value>
|
|
|
|
|
</property>
|
2004-04-16 06:31:48 +00:00
|
|
|
|
</bean></programlisting>
|
|
|
|
|
|
|
|
|
|
<para>The <literal>loginFormUrl</literal> is where the filter will
|
|
|
|
|
redirect the user's browser if they request a secure HTTP resource but
|
|
|
|
|
they are not authenticated. If the user is authenticated, a "403
|
|
|
|
|
Forbidden" response will be returned to the browser. All paths are
|
|
|
|
|
relative to the web application root.</para>
|
|
|
|
|
|
|
|
|
|
<para>The <literal>SecurityEnforcementFilter</literal> primarily
|
|
|
|
|
provides redirection and session management support. It delegates
|
|
|
|
|
actual <literal>FilterInvocation</literal> security decisions to the
|
|
|
|
|
configured <literal>FilterSecurityInterceptor</literal>.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>Like any other security interceptor, the
|
|
|
|
|
<literal>FilterSecurityInterceptor</literal> requires a reference to
|
|
|
|
|
an <literal>AuthenticationManager</literal>,
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>AccessDecisionManager</literal> and
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>RunAsManager</literal>, which are each discussed in separate
|
|
|
|
|
sections below. The <literal>FilterSecurityInterceptor</literal> is
|
|
|
|
|
also configured with configuration attributes that apply to different
|
|
|
|
|
HTTP URL requests. A full discussion of configuration attributes is
|
|
|
|
|
provided in the High Level Design section of this document.</para>
|
|
|
|
|
|
|
|
|
|
<para>The <literal>FilterSecurityInterceptor</literal> can be
|
|
|
|
|
configured with configuration attributes in two ways. The first is via
|
|
|
|
|
a property editor and the application context, which is shown above.
|
|
|
|
|
The second is via writing your own
|
|
|
|
|
<literal>ObjectDefinitionSource</literal>, although this is beyond the
|
|
|
|
|
scope of this document. Irrespective of the approach used, the
|
|
|
|
|
<literal>ObjectDefinitionSource</literal> is responsible for returning
|
|
|
|
|
a <literal>ConfigAttributeDefinition</literal> object that contains
|
|
|
|
|
all of the configuration attributes associated with a single secure
|
|
|
|
|
HTTP URL.</para>
|
|
|
|
|
|
|
|
|
|
<para>It should be noted that the
|
|
|
|
|
<literal>FilterSecurityInterceptor.setObjectDefinitionSource()</literal>
|
|
|
|
|
method actually expects an instance of
|
|
|
|
|
<literal>FilterInvocationDefinitionSource</literal>. This is a marker
|
|
|
|
|
interface which subclasses <literal>ObjectDefinitionSource</literal>.
|
|
|
|
|
It simply denotes the <literal>ObjectDefinitionSource</literal>
|
|
|
|
|
understands <literal>FilterInvocation</literal>s. In the interests of
|
|
|
|
|
simplicity we'll continue to refer to the
|
|
|
|
|
<literal>FilterInvocationDefinitionSource</literal> as an
|
|
|
|
|
<literal>ObjectDefinitionSource</literal>, as the distinction is of
|
|
|
|
|
little relevance to most users of the
|
|
|
|
|
<literal>FilterSecurityInterceptor</literal>.</para>
|
|
|
|
|
|
|
|
|
|
<para>If using the application context property editor approach (as
|
|
|
|
|
shown above), commas are used to delimit the different configuration
|
|
|
|
|
attributes that apply to each HTTP URL. Each configuration attribute
|
|
|
|
|
is assigned into its own <literal>SecurityConfig</literal> object. The
|
|
|
|
|
<literal>SecurityConfig</literal> object is discussed in the High
|
|
|
|
|
Level Design section. The <literal>ObjectDefinitionSource</literal>
|
|
|
|
|
created by the property editor,
|
|
|
|
|
<literal>FilterInvocationDefinitionSource</literal>, matches
|
|
|
|
|
configuration attributes against <literal>FilterInvocations</literal>
|
2004-04-09 09:51:23 +00:00
|
|
|
|
based on expression evaluation of the request URL. Two standard
|
|
|
|
|
expression syntaxes are supported. The default is to treat all
|
|
|
|
|
expressions as regular expressions. Alternatively, the presence of a
|
|
|
|
|
<literal>PATTERN_TYPE_APACHE_ANT</literal> directive will cause all
|
|
|
|
|
expressions to be treated as Apache Ant paths. It is not possible to
|
|
|
|
|
mix expression syntaxes within the same definition. For example, the
|
|
|
|
|
earlier configuration could be generated using Apache Ant paths as
|
2004-04-11 12:09:08 +00:00
|
|
|
|
follows:</para>
|
2004-04-09 09:51:23 +00:00
|
|
|
|
|
|
|
|
|
<para><programlisting><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
|
|
|
|
|
PATTERN_TYPE_APACHE_ANT
|
|
|
|
|
/secure/super/**=ROLE_WE_DONT_HAVE
|
|
|
|
|
/secure/**=ROLE_SUPERVISOR,ROLE_TELLER
|
|
|
|
|
</value>
|
|
|
|
|
</property>
|
|
|
|
|
</bean></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>Irrespective of the type of expression syntax used, expressions
|
|
|
|
|
are always evaluated in the order they are defined. Thus it is
|
|
|
|
|
important that more specific expressions are defined higher in the
|
|
|
|
|
list than less specific expressions. This is reflected in our example
|
|
|
|
|
above, where the more specific <literal>/secure/super/</literal>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
pattern appears higher than the less specific
|
2004-04-09 09:51:23 +00:00
|
|
|
|
<literal>/super/</literal> pattern. If they were reversed, the
|
|
|
|
|
<literal>/super/</literal> pattern would always match and the
|
2004-04-11 12:09:08 +00:00
|
|
|
|
<literal>/secure/super/</literal> pattern would never be
|
|
|
|
|
evaluated.</para>
|
2004-04-09 09:51:23 +00:00
|
|
|
|
|
|
|
|
|
<para>The special keyword
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON</literal> causes
|
|
|
|
|
the <literal>FilterInvocationDefinitionSource</literal> to
|
|
|
|
|
automatically convert a request URL to lowercase before comparison
|
2004-04-09 09:51:23 +00:00
|
|
|
|
against the expressions. Whilst by default the case of the request URL
|
|
|
|
|
is not converted, it is generally recommended to use
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON</literal> and
|
2004-04-09 09:51:23 +00:00
|
|
|
|
write each expression assuming lowercase.</para>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
|
|
|
|
|
<para>As with other security interceptors, the
|
|
|
|
|
<literal>validateConfigAttributes</literal> property is observed. When
|
|
|
|
|
set to <literal>true</literal> (the default), at startup time the
|
|
|
|
|
<literal>FilterSecurityInterceptor</literal> will evaluate if the
|
|
|
|
|
provided configuration attributes are valid. It does this by checking
|
|
|
|
|
each configuration attribute can be processed by either the
|
|
|
|
|
<literal>AccessDecisionManager</literal> or the
|
|
|
|
|
<literal>RunAsManager</literal>. If neither of these can process a
|
|
|
|
|
given configuration attribute, an exception is thrown.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</sect2>
|
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
|
|
<sect1 id="security-authentication">
|
|
|
|
|
<title>Authentication</title>
|
|
|
|
|
|
|
|
|
|
<sect2 id="security-authentication-requests">
|
|
|
|
|
<title>Authentication Requests</title>
|
|
|
|
|
|
|
|
|
|
<para>Authentication requires a way for client code to present its
|
|
|
|
|
security identification to the Acegi Security System for Spring. This
|
|
|
|
|
is the role of the <literal>Authentication</literal> interface. The
|
|
|
|
|
<literal>Authentication</literal> interface holds three important
|
|
|
|
|
objects: the principal (the identity of the caller), the credentials
|
|
|
|
|
(the proof of the identity of the caller, such as a password), and the
|
|
|
|
|
authorities that have been granted to the principal. The principal and
|
|
|
|
|
its credentials are populated by the client code, whilst the granted
|
|
|
|
|
authorities are populated by the
|
|
|
|
|
<literal>AuthenticationManager</literal>. The Acegi Security System
|
|
|
|
|
for Spring includes several concrete Authentication
|
|
|
|
|
implementations:</para>
|
|
|
|
|
|
|
|
|
|
<itemizedlist spacing="compact">
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>UsernamePasswordAuthenticationToken</literal>
|
|
|
|
|
allows a username and password to be presented as the principal
|
2004-04-03 05:37:20 +00:00
|
|
|
|
and credentials respectively. It is also what is created by the
|
|
|
|
|
HTTP Session Authentication system.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>TestingAuthenticationToken</literal> facilitates
|
|
|
|
|
unit testing by automatically being considered an authenticated
|
|
|
|
|
object by its associated
|
|
|
|
|
<literal>AuthenticationProvider</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>RunAsUserToken</literal> is used by the default
|
|
|
|
|
run-as authentication replacement implementation. This is
|
|
|
|
|
discussed further in the Run-As Authentication Replacement
|
|
|
|
|
section.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>PrincipalAcegiUserToken</literal> and
|
|
|
|
|
<literal>JettyAcegiUserToken</literal> implement
|
|
|
|
|
<literal>AuthByAdapter</literal> (a subclass of
|
|
|
|
|
<literal>Authentication</literal>) and are used whenever
|
|
|
|
|
authentication is completed by Acegi Security System for Spring
|
|
|
|
|
container adapters. This is discussed further in the Container
|
|
|
|
|
Adapters section.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
</itemizedlist>
|
|
|
|
|
|
|
|
|
|
<para>The authorities granted to a principal are represented by the
|
|
|
|
|
<literal>GrantedAuthority</literal> interface. The
|
|
|
|
|
<literal>GrantedAuthority</literal> interface is discussed at length
|
|
|
|
|
in the Authorization section.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
|
|
<sect2 id="security-authentication-manager">
|
|
|
|
|
<title>Authentication Manager</title>
|
|
|
|
|
|
|
|
|
|
<para>As discussed in the Security Interception section, the
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>AbstractSecurityInterceptor</literal> extracts the
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>Authentication</literal> object from the
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>SecureContext</literal> in the
|
|
|
|
|
<literal>ContextHolder</literal>. This is then passed to an
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>AuthenticationManager</literal>. The
|
|
|
|
|
<literal>AuthenticationManager</literal> interface is very
|
|
|
|
|
simple:</para>
|
|
|
|
|
|
|
|
|
|
<programlisting>public Authentication authenticate(Authentication authentication) throws AuthenticationException;</programlisting>
|
|
|
|
|
|
|
|
|
|
<para>Implementations of <literal>AuthenticationManager</literal> are
|
|
|
|
|
required to throw an <literal>AuthenticationException</literal> should
|
|
|
|
|
authentication fail, or return a fully populated
|
|
|
|
|
<literal>Authentication</literal> object. In particular, the returned
|
|
|
|
|
<literal>Authentication</literal> object should contain an array of
|
|
|
|
|
<literal>GrantedAuthority</literal> objects. The
|
|
|
|
|
<literal>SecurityInterceptor</literal> places the populated
|
|
|
|
|
<literal>Authentication</literal> object back in the
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>SecureContext</literal> in the
|
|
|
|
|
<literal>ContextHolder</literal>, overwriting the original
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>Authentication</literal> object.</para>
|
|
|
|
|
|
|
|
|
|
<para>The <literal>AuthenticationException</literal> has a number of
|
|
|
|
|
subclasses. The most important are
|
|
|
|
|
<literal>BadCredentialsException</literal> (an incorrect principal or
|
|
|
|
|
credentials), <literal>DisabledException</literal> and
|
|
|
|
|
<literal>LockedException</literal>. The latter two exceptions indicate
|
|
|
|
|
the principal was found, but the credentials were not checked and
|
|
|
|
|
authentication is denied. An
|
|
|
|
|
<literal>AuthenticationServiceException</literal> is also provided,
|
|
|
|
|
which indicates the authentication system could not process the
|
|
|
|
|
request (eg a database was unavailable).</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-authentication-provider">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>Provider-Based Authentication</title>
|
|
|
|
|
|
|
|
|
|
<para>Whilst the basic <literal>Authentication</literal> and
|
|
|
|
|
<literal>AuthenticationManager</literal> interfaces enable users to
|
|
|
|
|
develop their own authentication systems, users should consider using
|
2004-04-03 05:37:20 +00:00
|
|
|
|
the provider-based authentication packages provided by the Acegi
|
2004-03-16 23:57:17 +00:00
|
|
|
|
Security System for Spring. The key class,
|
|
|
|
|
<literal>ProviderManager</literal>, is configured via the bean context
|
|
|
|
|
with a list of <literal>AuthenticationProvider</literal>s:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting><bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
|
|
|
|
<property name="providers">
|
|
|
|
|
<list>
|
|
|
|
|
<ref bean="daoAuthenticationProvider"/>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<ref bean="someOtherAuthenticationProvider"/>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</list>
|
|
|
|
|
</property>
|
|
|
|
|
</bean></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para><literal>ProviderManager</literal> calls a series of registered
|
|
|
|
|
<literal>AuthenticationProvider</literal> implementations, until one
|
|
|
|
|
is found that indicates it is able to authenticate a given
|
|
|
|
|
<literal>Authentication</literal> class. When the first compatible
|
|
|
|
|
<literal>AuthenticationProvider</literal> is located, it is passed the
|
|
|
|
|
authentication request. The <literal>AuthenticationProvider</literal>
|
|
|
|
|
will then either throw an <literal>AuthenticationException</literal>
|
|
|
|
|
or return a fully populated <literal>Authentication</literal>
|
|
|
|
|
object.</para>
|
|
|
|
|
|
|
|
|
|
<para>Note the <literal>ProviderManager</literal> may throw a
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>ProviderNotFoundException</literal> (a subclass of
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>AuthenticationException</literal>) if it none of the
|
|
|
|
|
registered <literal>AuthenticationProviders</literal> can validate the
|
|
|
|
|
<literal>Authentication</literal> object.</para>
|
|
|
|
|
|
|
|
|
|
<para>Several <literal>AuthenticationProvider</literal>
|
|
|
|
|
implementations are provided with the Acegi Security System for
|
|
|
|
|
Spring:</para>
|
|
|
|
|
|
|
|
|
|
<para><itemizedlist spacing="compact">
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>TestingAuthenticationProvider</literal> is able
|
|
|
|
|
to authenticate a <literal>TestingAuthenticationToken</literal>.
|
|
|
|
|
The limit of its authentication is simply to treat whatever is
|
|
|
|
|
contained in the <literal>TestingAuthenticationToken</literal>
|
|
|
|
|
as valid. This makes it ideal for use during unit testing, as
|
|
|
|
|
you can create an <literal>Authentication</literal> object with
|
|
|
|
|
precisely the <literal>GrantedAuthority</literal> objects
|
2004-04-03 05:37:20 +00:00
|
|
|
|
required for calling a given method. You definitely would not
|
|
|
|
|
register this <literal>AuthenticationProvider</literal> on a
|
|
|
|
|
production system.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>DaoAuthenticationProvider</literal> is able to
|
|
|
|
|
authenticate a
|
|
|
|
|
<literal>UsernamePasswordAuthenticationToken</literal> by
|
|
|
|
|
accessing an authentication respository via a data access
|
2004-04-03 05:37:20 +00:00
|
|
|
|
object. This is discussed further below, as it is the main way
|
|
|
|
|
authentication is initially handled.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>RunAsImplAuthenticationToken</literal> is able to
|
|
|
|
|
authenticate a <literal>RunAsUserToken</literal>. This is
|
|
|
|
|
discussed further in the Run-As Authentication Replacement
|
2004-04-03 05:37:20 +00:00
|
|
|
|
section. You would not register this
|
|
|
|
|
<literal>AuthenticationProvider</literal> if you were not using
|
|
|
|
|
run-as replacement.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>AuthByAdapterProvider</literal> is able to
|
|
|
|
|
authenticate any <literal>AuthByAdapter</literal> (a subclass of
|
|
|
|
|
<literal>Authentication</literal> used with container adapters).
|
2004-04-03 05:37:20 +00:00
|
|
|
|
This is discussed further in the Container Adapters section. You
|
|
|
|
|
would not register this
|
|
|
|
|
<literal>AuthenticationProvider</literal> if you were not using
|
|
|
|
|
container adapters.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</listitem>
|
|
|
|
|
</itemizedlist></para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-authentication-provider-dao">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>Data Access Object Authentication Provider</title>
|
|
|
|
|
|
|
|
|
|
<para>The Acegi Security System for Spring includes a
|
|
|
|
|
production-quality <literal>AuthenticationProvider</literal>
|
|
|
|
|
implementation called <literal>DaoAuthenticationProvider</literal>.
|
|
|
|
|
This authentication provider is able to authenticate a
|
|
|
|
|
<literal>UsernamePasswordAuthenticationToken</literal> by obtaining
|
|
|
|
|
authentication details from a data access object configured at bean
|
|
|
|
|
creation time:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting><bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
|
|
|
|
|
<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
|
|
|
|
|
</bean></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>For a class to be able to provide the
|
|
|
|
|
<literal>DaoAuthenticationProvider</literal> with access to an
|
|
|
|
|
authentication repository, it must implement the
|
|
|
|
|
<literal>AuthenticationDao</literal> interface:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting>public User loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;</programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>The <literal>User</literal> object holds basic information such
|
|
|
|
|
as the username, password, granted authorities and whether the user is
|
|
|
|
|
enabled or disabled.</para>
|
|
|
|
|
|
|
|
|
|
<para>Given <literal>AuthenticationDao</literal> is so simple to
|
|
|
|
|
implement, it should be easy for users to retrieve authentication
|
|
|
|
|
information using a persistence strategy of their choice.</para>
|
|
|
|
|
|
|
|
|
|
<para>A design decision was made not to support account locking in the
|
|
|
|
|
<literal>DaoAuthenticationProvider</literal>, as doing so would have
|
|
|
|
|
increased the complexity of the <literal>AuthenticationDao</literal>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
interface. For instance, a method would be required to increase the
|
|
|
|
|
count of unsuccessful authentication attempts. Such functionality
|
|
|
|
|
could be easily provided in a new
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>AuthenticationManager</literal> or
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>AuthenticationProvider</literal> implementation if it were
|
|
|
|
|
desired.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-authentication-provider-in-memory">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>In-Memory Authentication</title>
|
|
|
|
|
|
|
|
|
|
<para>Whilst it is easy to use the
|
|
|
|
|
<literal>DaoAuthenticationProvider</literal> and create a custom
|
|
|
|
|
<literal>AuthenticationDao</literal> implementation that extracts
|
|
|
|
|
information from a persistence engine of choice, many applications do
|
|
|
|
|
not require such complexity. One alternative is to configure an
|
2004-04-03 05:37:20 +00:00
|
|
|
|
authentication repository in the application context itself using the
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>InMemoryDaoImpl</literal>:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting><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></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>The <literal>userMap</literal> property contains each of the
|
|
|
|
|
usernames, passwords, a list of granted authorities and an optional
|
|
|
|
|
enabled/disabled keyword. Commas delimit each token. The username must
|
|
|
|
|
appear to the left of the equals sign, and the password must be the
|
|
|
|
|
first token to the right of the equals sign. The
|
|
|
|
|
<literal>enabled</literal> and <literal>disabled</literal> keywords
|
|
|
|
|
(case insensitive) may appear in the second or any subsequent token.
|
|
|
|
|
Any remaining tokens are treated as granted authorities, which are
|
|
|
|
|
created as <literal>GrantedAuthorityImpl</literal> objects (refer to
|
|
|
|
|
the Authorization section for further discussion on granted
|
2004-04-03 05:37:20 +00:00
|
|
|
|
authorities). Note that if a user has no password and/or no granted
|
2004-03-16 23:57:17 +00:00
|
|
|
|
authorities, the user will not be created in the in-memory
|
|
|
|
|
authentication repository.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-authentication-provider-jdbc">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>JDBC Authentication</title>
|
|
|
|
|
|
|
|
|
|
<para>The Acegi Security System for Spring also includes an
|
|
|
|
|
authentication provider that can obtain authentication information
|
|
|
|
|
from a JDBC data source. The typical configuration for the
|
|
|
|
|
<literal>JdbcDaoImpl</literal> is shown below:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
|
|
|
|
|
<property name="driverClassName"><value>org.hsqldb.jdbcDriver</value></property>
|
|
|
|
|
<property name="url"><value>jdbc:hsqldb:hsql://localhost:9001</value></property>
|
|
|
|
|
<property name="username"><value>sa</value></property>
|
|
|
|
|
<property name="password"><value></value></property>
|
|
|
|
|
</bean>
|
|
|
|
|
|
|
|
|
|
<bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl">
|
|
|
|
|
<property name="dataSource"><ref bean="dataSource"/></property>
|
|
|
|
|
</bean></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>You can use different relational database management systems by
|
|
|
|
|
modifying the <literal>DriverManagerDataSource</literal> shown above.
|
|
|
|
|
Irrespective of the database used, a standard schema must be used as
|
2004-04-03 05:37:20 +00:00
|
|
|
|
indicated in <literal>dbinit.txt</literal>. Of particular note is the
|
|
|
|
|
database must return responses that treat the username as case
|
|
|
|
|
insensitive, in order to comply with the
|
|
|
|
|
<literal>AuthenticationDao</literal> contract.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<para>The Acegi Security System for Spring ships with a Hypersonic SQL
|
|
|
|
|
instance that has the required authentication information and sample
|
|
|
|
|
data already populated. To use this server, simply execute the
|
|
|
|
|
<literal>server.bat</literal> or <literal>server.sh</literal> script
|
|
|
|
|
included in the distribution. This will load a new database server
|
|
|
|
|
instance that will service requests made to the URL indicated in the
|
|
|
|
|
bean context configuration shown above.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-authentication-recommendations">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>Authentication Recommendations</title>
|
|
|
|
|
|
|
|
|
|
<para>With the heavy use of interfaces throughout the authentication
|
|
|
|
|
system (<literal>Authentication</literal>,
|
|
|
|
|
<literal>AuthenticationManager</literal>,
|
|
|
|
|
<literal>AuthenticationProvider</literal> and
|
|
|
|
|
<literal>AuthenticationDao</literal>) it might be confusing to a new
|
|
|
|
|
user to know which part of the authentication system to customize. In
|
|
|
|
|
general, the following is recommended:</para>
|
|
|
|
|
|
|
|
|
|
<itemizedlist>
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Use the
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>UsernamePasswordAuthenticationToken</literal>
|
|
|
|
|
implementation where possible.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>If you simply need to implement a new authentication
|
|
|
|
|
repository (eg to obtain user details from your application’s
|
|
|
|
|
existing database), use the
|
|
|
|
|
<literal>DaoAuthenticationProvider</literal> along with the
|
|
|
|
|
<literal>AuthenticationDao</literal>. It is the fastest and safest
|
|
|
|
|
way to integrate an external database.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<listitem>
|
|
|
|
|
<para>If you're using Container Adapters or a
|
|
|
|
|
<literal>RunAsManager</literal> that replaces the
|
|
|
|
|
<literal>Authentication</literal> object, ensure you have
|
|
|
|
|
registered the <literal>AuthByAdapterProvider</literal> and
|
|
|
|
|
<literal>RunAsManagerImplProvider</literal> respectively with your
|
|
|
|
|
<literal>ProviderManager</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<listitem>
|
|
|
|
|
<para>Never enable the
|
|
|
|
|
<literal>TestingAuthenticationProvider</literal> on a production
|
|
|
|
|
system. Doing so will allow any client to simply present a
|
|
|
|
|
<literal>TestingAuthenticationToken</literal> and obtain whatever
|
|
|
|
|
access they request.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Adding a new <literal>AuthenticationProvider</literal> is
|
|
|
|
|
sufficient to support most custom authentication requirements.
|
|
|
|
|
Only unusual requirements would require the
|
|
|
|
|
<literal>ProviderManager</literal> to be replaced with a different
|
|
|
|
|
<literal>AuthenticationManager</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
</itemizedlist>
|
|
|
|
|
</sect2>
|
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
|
|
<sect1 id="security-authorization">
|
|
|
|
|
<title>Authorization</title>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-authorization-granted-authorities">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>Granted Authorities</title>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>As briefly mentioned in the Authentication section, all
|
|
|
|
|
<literal>Authentication</literal> implementations are required to
|
|
|
|
|
store an array of <literal>GrantedAuthority</literal> objects. These
|
|
|
|
|
represent the authorities that have been granted to the principal. The
|
|
|
|
|
<literal>GrantedAuthority</literal> objects are inserted into the
|
|
|
|
|
<literal>Authentication</literal> object by the
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>AuthenticationManager</literal> and are later read by
|
|
|
|
|
<literal>AccessDecisionManager</literal>s when making authorization
|
|
|
|
|
decisions.</para>
|
|
|
|
|
|
|
|
|
|
<para><literal>GrantedAuthority</literal> is an interface with only
|
|
|
|
|
one method:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting>public String getAuthority();</programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>This method allows <literal>AccessDecisionManager</literal>s to
|
|
|
|
|
obtain a precise <literal>String</literal> representation of the
|
|
|
|
|
<literal>GrantedAuthority</literal>. By returning a representation as
|
|
|
|
|
a <literal>String</literal>, a <literal>GrantedAuthority</literal> can
|
|
|
|
|
be easily "read" by most <literal>AccessDecisionManager</literal>s. If
|
|
|
|
|
a <literal>GrantedAuthority</literal> cannot be precisely represented
|
|
|
|
|
as a <literal>String</literal>, the
|
|
|
|
|
<literal>GrantedAuthority</literal> is considered "complex" and
|
|
|
|
|
<literal>getAuthority()</literal> must return
|
|
|
|
|
<literal>null</literal>.</para>
|
|
|
|
|
|
|
|
|
|
<para>An example of a "complex" <literal>GrantedAuthority</literal>
|
|
|
|
|
would be an implementation that stores a list of operations and
|
|
|
|
|
authority thresholds that apply to different customer account numbers.
|
|
|
|
|
Representing this complex <literal>GrantedAuthority</literal> as a
|
|
|
|
|
<literal>String</literal> would be quite complex, and as a result the
|
|
|
|
|
<literal>getAuthority()</literal> method should return
|
|
|
|
|
<literal>null</literal>. This will indicate to any
|
|
|
|
|
<literal>AccessDecisionManager</literal> that it will need to
|
|
|
|
|
specifically support the <literal>GrantedAuthority</literal>
|
|
|
|
|
implementation in order to understand its contents.</para>
|
|
|
|
|
|
|
|
|
|
<para>The Acegi Security System for Spring includes one concrete
|
|
|
|
|
<literal>GrantedAuthority</literal> implementation,
|
|
|
|
|
<literal>GrantedAuthorityImpl</literal>. This allows any
|
|
|
|
|
user-specified <literal>String</literal> to be converted into a
|
|
|
|
|
<literal>GrantedAuthority</literal>. All
|
|
|
|
|
<literal>AuthenticationProvider</literal>s included with the security
|
2004-04-03 05:37:20 +00:00
|
|
|
|
architecture use <literal>GrantedAuthorityImpl</literal> to populate
|
2004-03-16 23:57:17 +00:00
|
|
|
|
the <literal>Authentication</literal> object.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-authorization-access-decision-managers">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>Access Decision Managers</title>
|
|
|
|
|
|
|
|
|
|
<para>The <literal>AccessDecisionManager</literal> is called by the
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>AbstractSecurityInterceptor</literal> and is responsible for
|
|
|
|
|
making final access control decisions. The
|
|
|
|
|
<literal>AccessDecisionManager</literal> interface contains three
|
2004-03-16 23:57:17 +00:00
|
|
|
|
methods:</para>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para><programlisting>public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException;
|
|
|
|
|
public boolean supports(ConfigAttribute attribute);
|
|
|
|
|
public boolean supports(Class clazz);</programlisting></para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<para>As can be seen from the first method, the
|
|
|
|
|
<literal>AccessDecisionManager</literal> is passed via method
|
|
|
|
|
parameters all information that is likely to be of value in assessing
|
2004-04-03 05:37:20 +00:00
|
|
|
|
an authorization decision. In particular, passing the secure
|
|
|
|
|
<literal>Object</literal> enables those arguments contained in the
|
|
|
|
|
actual secure object invocation to be inspected. For example, let's
|
|
|
|
|
assume the secure object was a <literal>MethodInvocation</literal>. It
|
|
|
|
|
would be easy to query the <literal>MethodInvocation</literal> for any
|
|
|
|
|
<literal>Customer</literal> argument, and then implement some sort of
|
|
|
|
|
security logic in the <literal>AccessDecisionManager</literal> to
|
|
|
|
|
ensure the principal is permitted to operate on that customer.
|
|
|
|
|
Implementations are expected to throw an
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>AccessDeniedException</literal> if access is denied.</para>
|
|
|
|
|
|
|
|
|
|
<para>The <literal>supports(ConfigAttribute)</literal> method is
|
2004-04-03 05:37:20 +00:00
|
|
|
|
called by the <literal>AbstractSecurityInterceptor</literal> at
|
|
|
|
|
startup time to determine if the
|
|
|
|
|
<literal>AccessDecisionManager</literal> can process the passed
|
|
|
|
|
<literal>ConfigAttribute</literal>. The
|
|
|
|
|
<literal>supports(Class)</literal> method is called by a security
|
|
|
|
|
interceptor implementation to ensure the configured
|
|
|
|
|
<literal>AccessDecisionManager</literal> supports the type of secure
|
|
|
|
|
object that the security interceptor will present.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-authorization-voting-decision-manager">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>Voting Decision Manager</title>
|
|
|
|
|
|
|
|
|
|
<para>Whilst users can implement their own
|
|
|
|
|
<literal>AccessDecisionManager</literal> to control all aspects of
|
2004-04-03 05:37:20 +00:00
|
|
|
|
authorization, the Acegi Security System for Spring includes several
|
|
|
|
|
<literal>AccessDecisionManager</literal> implementations that are
|
|
|
|
|
based on voting. Using this approach, a series of
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>AccessDecisionVoter</literal> implementations are polled on
|
|
|
|
|
an authorization decision. The
|
|
|
|
|
<literal>AccessDecisionManager</literal> then decides whether or not
|
|
|
|
|
to throw an <literal>AccessDeniedException</literal> based on its
|
|
|
|
|
assessment of the votes.</para>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>The <literal>AccessDecisionVoter</literal> interface has three
|
2004-03-16 23:57:17 +00:00
|
|
|
|
methods:</para>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para><programlisting>public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config);
|
|
|
|
|
public boolean supports(ConfigAttribute attribute);
|
|
|
|
|
public boolean supports(Class clazz);</programlisting></para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>Concrete implementations return an <literal>int</literal>, with
|
|
|
|
|
possible values being reflected in the
|
|
|
|
|
<literal>AccessDecisionVoter</literal> static fields
|
|
|
|
|
<literal>ACCESS_ABSTAIN</literal>, <literal>ACCESS_DENIED</literal>
|
|
|
|
|
and <literal>ACCESS_GRANTED</literal>. A voting implementation will
|
|
|
|
|
return <literal>ACCESS_ABSTAIN</literal> if it has no opinion on an
|
2004-03-16 23:57:17 +00:00
|
|
|
|
authorization decision. If it does have an opinion, it must return
|
|
|
|
|
either <literal>ACCESS_DENIED</literal> or
|
|
|
|
|
<literal>ACCESS_GRANTED</literal>.</para>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>There are three concrete
|
|
|
|
|
<literal>AccessDecisionManager</literal>s provided with the Acegi
|
|
|
|
|
Security System for Spring that tally the votes. The
|
|
|
|
|
<literal>ConsensusBased</literal> implementation will grant or deny
|
|
|
|
|
access based on the consensus of non-abstain votes. Properties are
|
|
|
|
|
provided to control behavior in the event of an equality of votes or
|
|
|
|
|
if all votes are abstain. The <literal>AffirmativeBased</literal>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
implementation will grant access if one or more
|
|
|
|
|
<literal>ACCESS_GRANTED</literal> votes were received (ie a deny vote
|
|
|
|
|
will be ignored, provided there was at least one grant vote). Like the
|
|
|
|
|
<literal>ConsensusBased</literal> implementation, there is a parameter
|
|
|
|
|
that controls the behavior if all voters abstain. The
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>UnanimousBased</literal> provider expects unanimous
|
|
|
|
|
<literal>ACCESS_GRANTED</literal> votes in order to grant access,
|
|
|
|
|
ignoring abstains. It will deny access if there is any
|
|
|
|
|
<literal>ACCESS_DENIED</literal> vote. Like the other implementations,
|
|
|
|
|
there is a parameter that controls the behaviour if all voters
|
|
|
|
|
abstain.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<para>It is possible to implement a custom
|
|
|
|
|
<literal>AccessDecisionManager</literal> that tallies votes
|
|
|
|
|
differently. For example, votes from a particular
|
|
|
|
|
<literal>AccessDecisionVoter</literal> might receive additional
|
2004-04-03 05:37:20 +00:00
|
|
|
|
weighting, whilst a deny vote from a particular voter may have a veto
|
|
|
|
|
effect.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<para>There is one concrete <literal>AccessDecisionVoter</literal>
|
|
|
|
|
implementation provided with the Acegi Security System for Spring. The
|
|
|
|
|
<literal>RoleVoter</literal> class will vote if any ConfigAttribute
|
|
|
|
|
begins with <literal>ROLE_</literal>. It will vote to grant access if
|
|
|
|
|
there is a <literal>GrantedAuthority</literal> which returns a
|
|
|
|
|
<literal>String</literal> representation (via the
|
|
|
|
|
<literal>getAuthority()</literal> method) exactly equal to one or more
|
|
|
|
|
<literal>ConfigAttributes</literal> starting with
|
|
|
|
|
<literal>ROLE_</literal>. If there is no exact match of any
|
|
|
|
|
<literal>ConfigAttribute</literal> starting with
|
|
|
|
|
<literal>ROLE_</literal>, the <literal>RoleVoter</literal> will vote
|
|
|
|
|
to deny access. If no <literal>ConfigAttribute</literal> begins with
|
|
|
|
|
<literal>ROLE_</literal>, the voter will abstain.
|
|
|
|
|
<literal>RoleVoter</literal> is case sensitive on comparisons as well
|
|
|
|
|
as the <literal>ROLE_</literal> prefix.</para>
|
|
|
|
|
|
|
|
|
|
<para>It is possible to implement a custom
|
|
|
|
|
<literal>AccessDecisionVoter</literal>. Several examples are provided
|
|
|
|
|
in the Acegi Security System for Spring unit tests, including
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>ContactSecurityVoter</literal> and
|
|
|
|
|
<literal>DenyVoter</literal>. The
|
|
|
|
|
<literal>ContactSecurityVoter</literal> abstains from voting decisions
|
|
|
|
|
where a <literal>CONTACT_OWNED_BY_CURRENT_USER</literal>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>ConfigAttribute</literal> is not found. If voting, it queries
|
2004-04-03 05:37:20 +00:00
|
|
|
|
the <literal>MethodInvocation</literal> to extract the owner of the
|
|
|
|
|
<literal>Contact</literal> object that is subject of the method call.
|
|
|
|
|
It votes to grant access if the <literal>Contact</literal> owner
|
|
|
|
|
matches the principal presented in the
|
|
|
|
|
<literal>Authentication</literal> object. It could have just as easily
|
|
|
|
|
compared the <literal>Contact</literal> owner with some
|
|
|
|
|
<literal>GrantedAuthority</literal> the
|
|
|
|
|
<literal>Authentication</literal> object presented. All of this is
|
|
|
|
|
achieved with relatively few lines of code and demonstrates the
|
|
|
|
|
flexibility of the authorization model.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
|
|
<sect2 id="security-authorization-taglib">
|
|
|
|
|
<title>Authorization Tag Library</title>
|
|
|
|
|
|
|
|
|
|
<para>The Acegi Security System for Spring comes bundled with a JSP
|
|
|
|
|
tag library that eases JSP writing. The tag library is known as
|
|
|
|
|
<literal>authz</literal>.</para>
|
|
|
|
|
|
|
|
|
|
<para>This library allows you to easy develop JSP pages which
|
|
|
|
|
reference the security environment. For example,
|
|
|
|
|
<literal>authz</literal> allows you to determine if a principal holds
|
|
|
|
|
a particular granted authority, holds a group of granted authorities,
|
|
|
|
|
or does not hold a given granted authority.</para>
|
|
|
|
|
|
|
|
|
|
<sect3>
|
|
|
|
|
<title>Usage</title>
|
|
|
|
|
|
|
|
|
|
<para>The following JSP fragment illustrates how to use the
|
|
|
|
|
<literal>authz</literal> taglib:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting><authz:authorize ifAllGranted="ROLE_SUPERVISOR">
|
|
|
|
|
<td>
|
|
|
|
|
<A HREF="del.htm?id=<c:out value="${contact.id}"/>">Del</A>
|
|
|
|
|
</td>
|
|
|
|
|
</authz:authorize></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>This code was copied from the Contacts sample
|
|
|
|
|
application.</para>
|
|
|
|
|
|
|
|
|
|
<para>What this code says is: if the principal has been granted
|
|
|
|
|
ROLE_SUPERVISOR, allow the tag's body to be output.</para>
|
|
|
|
|
</sect3>
|
|
|
|
|
|
|
|
|
|
<sect3>
|
|
|
|
|
<title>Installation</title>
|
|
|
|
|
|
|
|
|
|
<para>Installation is a simple matter. Simply copy the
|
|
|
|
|
<literal>acegi-security-taglib.jar</literal> file into your
|
|
|
|
|
application's <literal>WEB-INF/lib</literal> folder. The tag library
|
|
|
|
|
includes it's TLD, which makes it easier to work with JSP 1.2+
|
|
|
|
|
containers.</para>
|
|
|
|
|
|
|
|
|
|
<para>If you are using a JSP 1.1 container, you will need to declare
|
|
|
|
|
the JSP tag library in your application's <literal>web.xml</literal>
|
|
|
|
|
file, with code such as this:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting><taglib>
|
|
|
|
|
<taglib-uri>http://acegisecurity.sf.net/authz</taglib-uri>
|
|
|
|
|
<taglib-location>/WEB-INF/authz.tld</taglib-location>
|
|
|
|
|
</taglib></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>For JSP 1.1 containers you will also need to extract the
|
|
|
|
|
<literal>authz.tld</literal> file from the
|
|
|
|
|
<literal>acegi-security-taglib.jar</literal> file and put it into
|
|
|
|
|
your application's <literal>WEB-INF/lib</literal> folder. Use a
|
|
|
|
|
regular Zip tool, or Java's JAR utility.</para>
|
|
|
|
|
</sect3>
|
|
|
|
|
|
|
|
|
|
<sect3>
|
|
|
|
|
<title>Reference</title>
|
|
|
|
|
|
|
|
|
|
<para>The <literal>authz:authorize</literal> tag declares the
|
|
|
|
|
following attributes:</para>
|
|
|
|
|
|
|
|
|
|
<para><itemizedlist spacing="compact">
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>ifAllGranted</literal>: All the listed roles
|
|
|
|
|
must be granted for the tag to output its body.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>ifAnyGranted</literal>: Any of the listed roles
|
|
|
|
|
must be granted for the tag to output its body.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>ifNotGranted</literal>: None of the listed
|
|
|
|
|
roles must be granted for the tag to output its body.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
</itemizedlist></para>
|
|
|
|
|
|
|
|
|
|
<para>You'll note that in each attribute you can list multiple
|
|
|
|
|
roles. Simply separate the roles using a comma. The
|
|
|
|
|
<literal>authorize</literal> tag ignores whitespace in
|
|
|
|
|
attributes.</para>
|
|
|
|
|
|
|
|
|
|
<para>The tag library logically ANDs all of it's parameters
|
|
|
|
|
together. This means that if you combine two or more attributes, all
|
|
|
|
|
attributes must be true for the tag to output it's body. Don't add
|
|
|
|
|
an <literal>ifAllGranted="ROLE_SUPERVISOR"</literal>, followed by an
|
|
|
|
|
<literal>ifNotGranted="ROLE_SUPERVISOR"</literal>, or you'll be
|
|
|
|
|
surprised to never see the tag's body.</para>
|
|
|
|
|
|
|
|
|
|
<para>By requiring all attributes to return true, it allows you to
|
|
|
|
|
create more complex authorization scenarios. For example, you could
|
|
|
|
|
declare an <literal>ifAllGranted="ROLE_SUPERVISOR"</literal> and an
|
|
|
|
|
<literal>ifNotGranted="ROLE_NEWBIE_SUPERVISOR"</literal> in the same
|
|
|
|
|
tag, in order to prevent new supervisors from seeing the tag body.
|
|
|
|
|
Although it would no doubt be simpler to use
|
|
|
|
|
<literal>ifAllGranted="ROLE_EXPERIENCED_SUPERVISOR"</literal> rather
|
|
|
|
|
than inserting NOT conditions into your design.</para>
|
|
|
|
|
|
|
|
|
|
<para>One last item: the tag verifies the authorizations in a
|
|
|
|
|
specific order: first <literal>ifNotGranted</literal>, then
|
|
|
|
|
<literal>ifAllGranted</literal>, and finally,
|
|
|
|
|
<literal>ifAnyGranted</literal>.</para>
|
|
|
|
|
</sect3>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-authorization-recommendations">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>Authorization Recommendations</title>
|
|
|
|
|
|
|
|
|
|
<para>Given there are several ways to achieve similar authorization
|
|
|
|
|
outcomes in the Acegi Security System for Spring, the following
|
|
|
|
|
general recommendations are made:</para>
|
|
|
|
|
|
|
|
|
|
<itemizedlist>
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Grant authorities using
|
|
|
|
|
<literal>GrantedAuthorityImpl</literal> where possible. Because it
|
|
|
|
|
is already supported by the Acegi Security System for Spring, you
|
|
|
|
|
avoid the need to create custom
|
|
|
|
|
<literal>AuthenticationManager</literal> or
|
|
|
|
|
<literal>AuthenticationProvider</literal> implementations simply
|
|
|
|
|
to populate the <literal>Authentication</literal> object with a
|
|
|
|
|
custom <literal>GrantedAuthority</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Most authorization decision rules can be easily satisfied by
|
|
|
|
|
writing an <literal>AccessDecisionVoter</literal> implementation
|
2004-04-03 05:37:20 +00:00
|
|
|
|
and using either <literal>ConsensusBased</literal>,
|
|
|
|
|
<literal>AffirmativeBased</literal> or
|
|
|
|
|
<literal>UnanimousBased</literal> as the
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>AccessDecisionManager</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
</itemizedlist>
|
|
|
|
|
</sect2>
|
|
|
|
|
</sect1>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect1 id="security-run-as">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>Run-As Authentication Replacement</title>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-run-as-purpose">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>Purpose</title>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>The <literal>AbstractSecurityInterceptor</literal> is able to
|
|
|
|
|
temporarily replace the <literal>Authentication</literal> object in
|
|
|
|
|
the <literal>SecureContext</literal> and
|
|
|
|
|
<literal>ContextHolder</literal> during the
|
|
|
|
|
<literal>SecurityInterceptorCallback</literal>. This only occurs if
|
|
|
|
|
the original <literal>Authentication</literal> object was successfully
|
|
|
|
|
processed by the <literal>AuthenticationManager</literal> and
|
|
|
|
|
<literal>AccessDecisionManager</literal>. The
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>RunAsManager</literal> will indicate the replacement
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>Authentication</literal> object, if any, that should be used
|
|
|
|
|
during the <literal>SecurityInterceptorCallback</literal>.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<para>By temporarily replacing the <literal>Authentication</literal>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
object during a <literal>SecurityInterceptorCallback</literal>, the
|
|
|
|
|
secured invocation will be able to call other objects which require
|
|
|
|
|
different authentication and authorization credentials. It will also
|
|
|
|
|
be able to perform any internal security checks for specific
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>GrantedAuthority</literal> objects.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-run-as-usage">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>Usage</title>
|
|
|
|
|
|
|
|
|
|
<para>A <literal>RunAsManager</literal> interface is provided by the
|
|
|
|
|
Acegi Security System for Spring:</para>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para><programlisting>public Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config);
|
|
|
|
|
public boolean supports(ConfigAttribute attribute);
|
|
|
|
|
public boolean supports(Class clazz);</programlisting></para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<para>The first method returns the <literal>Authentication</literal>
|
|
|
|
|
object that should replace the existing
|
|
|
|
|
<literal>Authentication</literal> object for the duration of the
|
|
|
|
|
method invocation. If the method returns <literal>null</literal>, it
|
|
|
|
|
indicates no replacement should be made. The second method is used by
|
2004-04-03 05:37:20 +00:00
|
|
|
|
the <literal>AbstractSecurityInterceptor</literal> as part of its
|
|
|
|
|
startup validation of configuration attributes. The
|
|
|
|
|
<literal>supports(Class)</literal> method is called by a security
|
|
|
|
|
interceptor implementation to ensure the configured
|
|
|
|
|
<literal>RunAsManager</literal> supports the type of secure object
|
|
|
|
|
that the security interceptor will present.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<para>One concrete implementation of a <literal>RunAsManager</literal>
|
|
|
|
|
is provided with the Acegi Security System for Spring. The
|
|
|
|
|
<literal>RunAsManagerImpl</literal> class returns a replacement
|
|
|
|
|
<literal>RunAsUserToken</literal> if any
|
|
|
|
|
<literal>ConfigAttribute</literal> starts with
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>RUN_AS_</literal>. If any such
|
|
|
|
|
<literal>ConfigAttribute</literal> is found, the replacement
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>RunAsUserToken</literal> will contain the same principal,
|
|
|
|
|
credentials and granted authorities as the original
|
|
|
|
|
<literal>Authentication</literal> object, along with a new
|
|
|
|
|
<literal>GrantedAuthorityImpl</literal> for each
|
|
|
|
|
<literal>RUN_AS_</literal> <literal>ConfigAttribute</literal>. Each
|
|
|
|
|
new <literal>GrantedAuthorityImpl</literal> will be prefixed with
|
|
|
|
|
<literal>ROLE_</literal>, followed by the <literal>RUN_AS</literal>
|
|
|
|
|
<literal>ConfigAttribute</literal>. For example, a
|
|
|
|
|
<literal>RUN_AS_SERVER</literal> will result in the replacement
|
|
|
|
|
<literal>RunAsUserToken</literal> containing a
|
|
|
|
|
<literal>ROLE_RUN_AS_SERVER</literal> granted authority.</para>
|
|
|
|
|
|
|
|
|
|
<para>The replacement <literal>RunAsUserToken</literal> is just like
|
|
|
|
|
any other <literal>Authentication</literal> object. It needs to be
|
|
|
|
|
authenticated by the <literal>AuthenticationManager</literal>,
|
2004-04-03 05:37:20 +00:00
|
|
|
|
probably via delegation to a suitable
|
|
|
|
|
<literal>AuthenticationProvider</literal>. The
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>RunAsImplAuthenticationProvider</literal> performs such
|
2004-04-03 05:37:20 +00:00
|
|
|
|
authentication. It simply accepts as valid any
|
|
|
|
|
<literal>RunAsUserToken</literal> presented.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<para>To ensure malicious code does not create a
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>RunAsUserToken</literal> and present it for guaranteed
|
2004-03-16 23:57:17 +00:00
|
|
|
|
acceptance by the <literal>RunAsImplAuthenticationProvider</literal>,
|
|
|
|
|
the hash of a key is stored in all generated tokens. The
|
|
|
|
|
<literal>RunAsManagerImpl</literal> and
|
|
|
|
|
<literal>RunAsImplAuthenticationProvider</literal> is created in the
|
|
|
|
|
bean context with the same key:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting><bean id="runAsManager" class="net.sf.acegisecurity.runas.RunAsManagerImpl">
|
|
|
|
|
<property name="key"><value>my_run_as_password</value></property>
|
|
|
|
|
</bean></programlisting><programlisting><bean id="runAsAuthenticationProvider" class="net.sf.acegisecurity.runas.RunAsImplAuthenticationProvider">
|
|
|
|
|
<property name="key"><value>my_run_as_password</value></property>
|
|
|
|
|
</bean></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>By using the same key, each <literal>RunAsUserToken</literal>
|
|
|
|
|
can be validated it was created by an approved
|
|
|
|
|
<literal>RunAsManagerImpl</literal>. The
|
|
|
|
|
<literal>RunAsUserToken</literal> is immutable after creation for
|
|
|
|
|
security reasons.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
</sect1>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect1 id="security-ui">
|
|
|
|
|
<title>User Interfacing with the ContextHolder</title>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-ui-purpose">
|
|
|
|
|
<title>Purpose</title>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>Everything presented so far assumes one thing: the
|
|
|
|
|
<literal>ContextHolder</literal> is populated with a valid
|
|
|
|
|
<literal>SecureContext</literal>, which in turn contains a valid
|
|
|
|
|
<literal>Authentication</literal> object. Develolpers are free to do
|
|
|
|
|
this in whichever way they like, such as directly calling the relevant
|
|
|
|
|
objects at runtime. However, several classes have been provided to
|
|
|
|
|
make this process transparent in many situations.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>The <literal>net.sf.acegisecurity.ui</literal> package is design
|
|
|
|
|
to make interfacing web application user interfaces with the
|
|
|
|
|
<literal>ContextHolder</literal> as simple as possible. There are two
|
|
|
|
|
major steps in doing this:</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para><itemizedlist spacing="compact">
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Actually authenticate the user and place the resulting
|
|
|
|
|
<literal>Authentication</literal> object in a "well-known
|
|
|
|
|
location".</para>
|
|
|
|
|
</listitem>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<listitem>
|
|
|
|
|
<para>Extract the <literal>Authentication</literal> object from
|
|
|
|
|
the "well-known location" and place in into the
|
|
|
|
|
<literal>ContextHolder</literal> for the duration of the secure
|
|
|
|
|
object invocation.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
</itemizedlist></para>
|
|
|
|
|
|
2004-04-11 12:09:08 +00:00
|
|
|
|
<para>There are several alternatives are available for the first step,
|
|
|
|
|
which will be briefly discussed in this chapter. The most popular
|
|
|
|
|
approach is HTTP Session Authentication, which uses the
|
|
|
|
|
<literal>HttpSession</literal> object and filters to authenticate the
|
|
|
|
|
user. Another approach is HTTP Basic Authentication, which allows
|
|
|
|
|
clients to use HTTP headers to present authentication information to
|
|
|
|
|
the Acegi Security System for Spring. The final approach is via
|
|
|
|
|
Container Adapters, which allow supported web containers to perform
|
|
|
|
|
the authentication themselves. HTTP Session Authentication is
|
|
|
|
|
discussed below, whilst Container Adapters are discussed in a separate
|
|
|
|
|
section.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-ui-http-session">
|
|
|
|
|
<title>HTTP Session Authentication</title>
|
|
|
|
|
|
|
|
|
|
<para>HTTP Session Authentication involves using the
|
|
|
|
|
<literal>AuthenticationProcessingFilter</literal> to process a login
|
|
|
|
|
form. The login form simply contains <literal>j_username</literal> and
|
|
|
|
|
<literal>j_password</literal> input fields, and posts to a URL that is
|
|
|
|
|
monitored by the filter (by default
|
|
|
|
|
<literal>j_acegi_security_check</literal>). The filter is defined in
|
2004-04-16 06:31:48 +00:00
|
|
|
|
<literal>web.xml</literal> behind a
|
|
|
|
|
<literal>FilterToBeanProxy</literal> as follows:</para>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
|
|
|
|
|
<para><programlisting><filter>
|
|
|
|
|
<filter-name>Acegi Authentication Processing Filter</filter-name>
|
2004-04-16 06:31:48 +00:00
|
|
|
|
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<init-param>
|
2004-04-16 06:31:48 +00:00
|
|
|
|
<param-name>targetClass</param-name>
|
|
|
|
|
<param-value>net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter</param-value>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
</init-param>
|
|
|
|
|
</filter>
|
|
|
|
|
|
|
|
|
|
<filter-mapping>
|
|
|
|
|
<filter-name>Acegi Authentication Processing Filter</filter-name>
|
|
|
|
|
<url-pattern>/*</url-pattern>
|
|
|
|
|
</filter-mapping></programlisting></para>
|
|
|
|
|
|
2004-04-16 06:31:48 +00:00
|
|
|
|
<para>For a discussion of <literal>FilterToBeanProxy</literal>, please
|
|
|
|
|
refer to the FilterInvocation Security Interceptor section. The
|
|
|
|
|
application context will need to define the
|
|
|
|
|
<literal>AuthenticationProcessingFilter</literal>:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting><bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
|
|
|
|
|
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
|
|
|
|
<property name="authenticationFailureUrl"><value>/acegilogin.jsp?login_error=1</value></property>
|
|
|
|
|
<property name="defaultTargetUrl"><value>/</value></property>
|
|
|
|
|
<property name="filterProcessesUrl"><value>/j_acegi_security_check</value></property>
|
|
|
|
|
</bean></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>The configured <literal>AuthenticationManager</literal>
|
|
|
|
|
processes each authentication request. If authentication fails, the
|
|
|
|
|
browser will be redirected to the
|
|
|
|
|
<literal>authenticationFailureUrl</literal>. The
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>AuthenticationException</literal> will be placed into the
|
|
|
|
|
<literal>HttpSession</literal> attribute indicated by
|
|
|
|
|
<literal>AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY</literal>,
|
|
|
|
|
enabling a reason to be provided to the user on the error page.</para>
|
|
|
|
|
|
|
|
|
|
<para>If authentication is successful, the resulting
|
|
|
|
|
<literal>Authentication</literal> object will be placed into the
|
|
|
|
|
<literal>HttpSession</literal> attribute indicated by
|
|
|
|
|
<literal>HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY</literal>.
|
|
|
|
|
This becomes the "well-known location" from which the
|
|
|
|
|
<literal>Authentication</literal> object is later extracted.</para>
|
|
|
|
|
|
2004-04-09 05:41:42 +00:00
|
|
|
|
<para>Once the <literal>HttpSession</literal> has been updated, the
|
|
|
|
|
browser will need to be redirected to the target URL. The target URL
|
|
|
|
|
is usually indicated by the <literal>HttpSession</literal> attribute
|
|
|
|
|
specified by
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>AuthenticationProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY</literal>.
|
|
|
|
|
This attribute is automatically set by the
|
|
|
|
|
<literal>SecurityEnforcementFilter</literal> when an
|
|
|
|
|
<literal>AuthenticationException</literal> occurs, so that after login
|
|
|
|
|
is completed the user can return to what they were trying to access.
|
|
|
|
|
If for some reason the <literal>HttpSession</literal> does not
|
|
|
|
|
indicate the target URL, the browser will be redirected to the
|
2004-04-16 06:31:48 +00:00
|
|
|
|
<literal>defaultTargetUrl</literal> property.</para>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
|
|
|
|
|
<para>Because this authentication approach is fully contained within a
|
|
|
|
|
single web application, HTTP Session Authentication is recommended to
|
|
|
|
|
be used instead of Container Adapters.</para>
|
|
|
|
|
</sect2>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
2004-04-11 13:14:19 +00:00
|
|
|
|
<sect2 id="security-ui-http-basic">
|
2004-04-11 12:09:08 +00:00
|
|
|
|
<title>HTTP Basic Authentication</title>
|
|
|
|
|
|
|
|
|
|
<para>Primarily to cater for the needs of remoting protocols such as
|
|
|
|
|
Hessian and Burlap, the Acegi Security System for Spring provides a
|
|
|
|
|
<literal>BasicProcessingFilter</literal> which is capable of
|
|
|
|
|
processing authentication credentials presented in HTTP headers (for
|
|
|
|
|
standard authentication of web browser users, we recommend HTTP
|
|
|
|
|
Session Authentication). The standard governing HTTP Basic
|
|
|
|
|
Authentication is defined by RFC 1945, Section 11, and the
|
2004-04-16 12:37:58 +00:00
|
|
|
|
<literal>BasicProcessingFilter</literal> conforms with this
|
|
|
|
|
RFC.</para>
|
2004-04-16 06:31:48 +00:00
|
|
|
|
|
|
|
|
|
<para>To implement HTTP Basic Authentication, it is necessary to add
|
|
|
|
|
the following filter to <literal>web.xml</literal>, behind a
|
|
|
|
|
<literal>FilterToBeanProxy</literal>:</para>
|
2004-04-11 12:09:08 +00:00
|
|
|
|
|
|
|
|
|
<para><programlisting><filter>
|
|
|
|
|
<filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
|
2004-04-16 06:31:48 +00:00
|
|
|
|
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
|
|
|
|
<init-param>
|
|
|
|
|
<param-name>targetClass</param-name>
|
|
|
|
|
<param-value>net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter</param-value>
|
|
|
|
|
</init-param>
|
2004-04-11 12:09:08 +00:00
|
|
|
|
</filter>
|
|
|
|
|
|
|
|
|
|
<filter-mapping>
|
|
|
|
|
<filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
|
|
|
|
|
<url-pattern>/*</url-pattern>
|
|
|
|
|
</filter-mapping></programlisting></para>
|
|
|
|
|
|
2004-04-16 06:31:48 +00:00
|
|
|
|
<para>For a discussion of <literal>FilterToBeanProxy</literal>, please
|
|
|
|
|
refer to the FilterInvocation Security Interceptor section. The
|
|
|
|
|
application context will need to define the
|
|
|
|
|
<literal>BasicProcessingFilter</literal>:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting><bean id="basicProcessingFilter" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter">
|
|
|
|
|
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
|
|
|
|
</bean></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>The configured <literal>AuthenticationManager</literal>
|
|
|
|
|
processes each authentication request. If authentication fails, a 403
|
|
|
|
|
(forbidden) response will be returned in response to the HTTP request.
|
|
|
|
|
If authentication is successful, the resulting
|
2004-04-11 12:09:08 +00:00
|
|
|
|
<literal>Authentication</literal> object will be placed into the
|
|
|
|
|
<literal>HttpSession</literal> attribute indicated by
|
|
|
|
|
<literal>HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY</literal>.
|
|
|
|
|
This becomes the "well-known location" from which the
|
|
|
|
|
<literal>Authentication</literal> object is later extracted.</para>
|
|
|
|
|
|
|
|
|
|
<para>If the authentication event was successful, or authentication
|
|
|
|
|
was not attempted because the HTTP header did not contain a supported
|
|
|
|
|
authentication request, the filter chain will continue as normal. The
|
|
|
|
|
only time the filter chain will be interrupted is if authentication
|
|
|
|
|
fails and a 403 response is returned, as discussed in the previous
|
|
|
|
|
paragraph.</para>
|
|
|
|
|
|
|
|
|
|
<para>HTTP Basic Authentication is recommended to be used instead of
|
|
|
|
|
Container Adapters. It can be used in conjunction with HTTP Session
|
|
|
|
|
Authentication, as demonstrated in the Contacts sample
|
|
|
|
|
application.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-ui-well-known">
|
|
|
|
|
<title>Well-Known Location Integration</title>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>Once a web application has used either HTTP Session
|
2004-04-11 12:09:08 +00:00
|
|
|
|
Authentication, HTTP Basic Authentication, or a Container Adapter, an
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>Authentication</literal> object will exist in a well-known
|
|
|
|
|
location. The final step in automatically integrating the user
|
|
|
|
|
interface with the backend security interceptor is to extract this
|
|
|
|
|
<literal>Authentication</literal> object from the well-known location
|
|
|
|
|
and place it into a <literal>SecureContext</literal> in the
|
|
|
|
|
<literal>ContextHolder</literal>.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<para>The <literal>AbstractIntegrationFilter</literal> and its
|
2004-04-03 05:37:20 +00:00
|
|
|
|
subclasses provide this well-known location integration. These classes
|
|
|
|
|
are standard filters, and at the start of each request they will
|
|
|
|
|
attempt to extract the <literal>Authentication</literal> object from a
|
|
|
|
|
well-known location. The <literal>Authentication</literal> object will
|
|
|
|
|
then be added to a <literal>SecureContext</literal>, the
|
|
|
|
|
<literal>SecureContext</literal> associated with the
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>ContextHolder</literal> for the duration of the request, and
|
2004-04-03 05:37:20 +00:00
|
|
|
|
the <literal>ContextHolder</literal> be cleared when the request is
|
|
|
|
|
finished. Four concrete subclasses of
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>AbstractIntegrationFilter</literal> are provided with the
|
|
|
|
|
Acegi Security System for Spring:</para>
|
|
|
|
|
|
|
|
|
|
<para><itemizedlist>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>HttpSessionIntegrationFilter</literal> is used
|
2004-04-11 12:09:08 +00:00
|
|
|
|
with HTTP Session Authentication, HTTP Basic Authentication, or
|
|
|
|
|
any other approach that populates the
|
|
|
|
|
<literal>HttpSession</literal> accordingly. It extracts the
|
|
|
|
|
<literal>Authentication</literal> object from the
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<literal>HttpSession</literal> attribute indicated by
|
|
|
|
|
<literal>HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>HttpRequestIntegrationFilter</literal> is used
|
2004-04-03 05:37:20 +00:00
|
|
|
|
with Catalina, Jetty and Resin Container Adapters. It extracts
|
|
|
|
|
the authentication information from
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>HttpServletRequest.getUserPrincipal()</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para><literal>JbossIntegrationFilter</literal> is used with the
|
|
|
|
|
JBoss Container Adapter. It extracts the authentication from
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>java:comp/env/security/subject</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>AutoIntegrationFilter</literal> automatically
|
|
|
|
|
determines which filter to use. This makes a web application WAR
|
|
|
|
|
file more portable, as the <literal>web.xml</literal> is not
|
2004-04-03 05:37:20 +00:00
|
|
|
|
hard-coded to a specific
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>AbstractIntegrationFilter</literal>.</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
</itemizedlist></para>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>To define the <literal>AutoIntegrationFilter</literal>
|
|
|
|
|
(recommended), simply add the following to your web.xml:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting><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></programlisting></para>
|
|
|
|
|
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<para>Once in the <literal>ContextHolder</literal>, the standard Acegi
|
|
|
|
|
Security System for Spring classes can be used. Because
|
|
|
|
|
<literal>ContextHolder</literal> is a standard object which is
|
|
|
|
|
populated using a filter at the container level, JSPs and Servlets do
|
|
|
|
|
not need to use Spring's MVC packages. This enables those applications
|
|
|
|
|
that use other MVC frameworks to still leverage Spring's other
|
|
|
|
|
capabilities, with full authentication and authorization support. The
|
|
|
|
|
<literal>debug.jsp</literal> page provided with the sample application
|
|
|
|
|
demonstrates accessing the <literal>ContextHolder</literal>
|
|
|
|
|
independent of Spring's MVC packages.</para>
|
|
|
|
|
</sect2>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
</sect1>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect1 id="security-container-adapters">
|
|
|
|
|
<title>Container Adapters</title>
|
|
|
|
|
|
|
|
|
|
<sect2 id="security-container-adapters-overview">
|
|
|
|
|
<title>Overview</title>
|
|
|
|
|
|
|
|
|
|
<para>Early versions of the Acegi Security System for Spring
|
|
|
|
|
exclusively used Container Adapters for interfacing authentication
|
|
|
|
|
with end users. Whilst this worked well, it required considerable time
|
|
|
|
|
to support multiple container versions and the configuration itself
|
|
|
|
|
was relatively time-consuming for developers. For this reason the HTTP
|
2004-04-11 12:09:08 +00:00
|
|
|
|
Session Authentication and HTTP Basic Authentication approaches were
|
|
|
|
|
developed, and are today recommended for most applications.</para>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
|
|
|
|
|
<para>Container Adapters enable the Acegi Security System for Spring
|
|
|
|
|
to integrate directly with the containers used to host end user
|
|
|
|
|
applications. This integration means that applications can continue to
|
|
|
|
|
leverage the authentication and authorization capabilities built into
|
|
|
|
|
containers (such as <literal>isUserInRole()</literal> and form-based
|
|
|
|
|
or basic authentication), whilst benefiting from the enhanced security
|
|
|
|
|
interception capabilities provided by the Acegi Security System for
|
|
|
|
|
Spring.</para>
|
|
|
|
|
|
|
|
|
|
<para>The integration between a container and the Acegi Security
|
|
|
|
|
System for Spring is achieved through an adapter. The adapter provides
|
|
|
|
|
a container-compatible user authentication provider, and needs to
|
|
|
|
|
return a container-compatible user object.</para>
|
|
|
|
|
|
|
|
|
|
<para>The adapter is instantiated by the container and is defined in a
|
|
|
|
|
container-specific configuration file. The adapter then loads a Spring
|
|
|
|
|
application context which defines the normal authentication manager
|
|
|
|
|
settings, such as the authentication providers that can be used to
|
|
|
|
|
authenticate the request. The application context is usually named
|
|
|
|
|
<literal>acegisecurity.xml</literal> and is placed in a
|
|
|
|
|
container-specific location.</para>
|
|
|
|
|
|
|
|
|
|
<para>The Acegi Security System for Spring currently supports Jetty,
|
|
|
|
|
Catalina (Tomcat), JBoss and Resin. Additional container adapters can
|
|
|
|
|
easily be written.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
|
|
<sect2 id="security-container-adapters-adapter-provider">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>Adapter Authentication Provider</title>
|
|
|
|
|
|
|
|
|
|
<para>As is always the case, the container adapter generated
|
|
|
|
|
<literal>Authentication</literal> object still needs to be
|
|
|
|
|
authenticated by an <literal>AuthenticationManager</literal> when
|
2004-04-03 05:37:20 +00:00
|
|
|
|
requested to do so by the
|
|
|
|
|
<literal>AbstractSecurityInterceptor</literal>. The
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>AuthenticationManager</literal> needs to be certain the
|
|
|
|
|
adapter-provided <literal>Authentication</literal> object is valid and
|
|
|
|
|
was actually authenticated by a trusted adapter.</para>
|
|
|
|
|
|
|
|
|
|
<para>Adapters create <literal>Authentication</literal> objects which
|
|
|
|
|
are immutable and implement the <literal>AuthByAdapter</literal>
|
|
|
|
|
interface. These objects store the hash of a key that is defined by
|
|
|
|
|
the adapter. This allows the <literal>Authentication</literal> object
|
|
|
|
|
to be validated by the <literal>AuthByAdapterProvider</literal>. This
|
|
|
|
|
authentication provider is defined as follows:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting><bean id="authByAdapterProvider" class="net.sf.acegisecurity.adapters.AuthByAdapterProvider">
|
|
|
|
|
<property name="key"><value>my_password</value></property>
|
|
|
|
|
</bean></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>The key must match the key that is defined in the
|
|
|
|
|
container-specific configuration file that starts the adapter. The
|
|
|
|
|
<literal>AuthByAdapterProvider</literal> automatically accepts as
|
|
|
|
|
valid any <literal>AuthByAdapter</literal> implementation that returns
|
|
|
|
|
the expected hash of the key.</para>
|
|
|
|
|
|
|
|
|
|
<para>To reiterate, this means the adapter will perform the initial
|
|
|
|
|
authentication using providers such as
|
|
|
|
|
<literal>DaoAuthenticationProvider</literal>, returning an
|
|
|
|
|
<literal>AuthByAdapter</literal> instance that contains a hash code of
|
2004-04-03 05:37:20 +00:00
|
|
|
|
the key. Later, when an application calls a security interceptor
|
|
|
|
|
managed resource, the <literal>AuthByAdapter</literal> instance in the
|
|
|
|
|
<literal>SecureContext</literal> in the
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>ContextHolder</literal> will be tested by the application's
|
|
|
|
|
<literal>AuthByAdapterProvider</literal>. There is no requirement for
|
|
|
|
|
additional authentication providers such as
|
|
|
|
|
<literal>DaoAuthenticationProvider</literal> within the
|
2004-04-03 05:37:20 +00:00
|
|
|
|
application-specific application context, as the only type of
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>Authentication</literal> instance that will be presented by
|
|
|
|
|
the application is from the container adapter.</para>
|
|
|
|
|
|
|
|
|
|
<para>Classloader issues are frequent with containers and the use of
|
|
|
|
|
container adapters illustrates this further. Each container requires a
|
|
|
|
|
very specific configuration. The installation instructions are
|
|
|
|
|
provided below. Once installed, please take the time to try the sample
|
|
|
|
|
application to ensure your container adapter is properly
|
|
|
|
|
configured.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-container-adapters-catalina">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>Catalina (Tomcat) Installation</title>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>The following was tested with Jakarta Tomcat 4.1.30 and 5.0.19.
|
|
|
|
|
We automatically test the following directions using our container
|
|
|
|
|
integration test system and these versions of Catalina
|
|
|
|
|
(Tomcat).</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<para><literal>$CATALINA_HOME</literal> refers to the root of your
|
|
|
|
|
Catalina (Tomcat) installation.</para>
|
|
|
|
|
|
|
|
|
|
<para>Edit your <literal>$CATALINA_HOME/conf/server.xml</literal> file
|
|
|
|
|
so the <literal><Engine></literal> section contains only one
|
|
|
|
|
active <literal><Realm></literal> entry. An example realm
|
|
|
|
|
entry:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting> <Realm className="net.sf.acegisecurity.adapters.catalina.CatalinaAcegiUserRealm"
|
|
|
|
|
appContextLocation="conf/acegisecurity.xml"
|
|
|
|
|
key="my_password" /></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>Be sure to remove any other <literal><Realm></literal>
|
|
|
|
|
entry from your <literal><Engine></literal> section.</para>
|
|
|
|
|
|
|
|
|
|
<para>Copy <literal>acegisecurity.xml</literal> into
|
|
|
|
|
<literal>$CATALINA_HOME/conf</literal>.</para>
|
|
|
|
|
|
|
|
|
|
<para>Copy <literal>acegi-security-catalina-server.jar</literal> into
|
|
|
|
|
<literal>$CATALINA_HOME/server/lib</literal>.</para>
|
|
|
|
|
|
|
|
|
|
<para>Copy the following files into
|
|
|
|
|
<literal>$CATALINA_HOME/common/lib</literal>:</para>
|
|
|
|
|
|
|
|
|
|
<itemizedlist>
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>aopalliance.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>spring.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>acegi-security-catalina-common.jar</literal></para>
|
|
|
|
|
</listitem>
|
2004-04-11 12:09:08 +00:00
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>commons-codec.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>burlap.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>hessian.jar</literal></para>
|
|
|
|
|
</listitem>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</itemizedlist>
|
|
|
|
|
|
|
|
|
|
<para>None of the above JAR files (or
|
|
|
|
|
<literal>acegi-security.jar</literal>) should be in your application's
|
|
|
|
|
<literal>WEB-INF/lib</literal>. The realm name indicated in your
|
|
|
|
|
<literal>web.xml</literal> does not matter with Catalina.</para>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
|
|
|
|
|
<para>We have received reports of problems using this Container
|
|
|
|
|
Adapter with Mac OS X. A work-around is to use a script such as
|
|
|
|
|
follows:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting>#!/bin/sh
|
|
|
|
|
export CATALINA_HOME="/Library/Tomcat"
|
|
|
|
|
export JAVA_HOME="/Library/Java/Home"
|
|
|
|
|
cd /
|
|
|
|
|
$CATALINA_HOME/bin/startup.sh</programlisting></para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-container-adapters-jetty">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>Jetty Installation</title>
|
|
|
|
|
|
|
|
|
|
<para>The following was tested with Jetty 4.2.18. We automatically
|
|
|
|
|
test the following directions using our container integration test
|
|
|
|
|
system and this version of Jetty.</para>
|
|
|
|
|
|
|
|
|
|
<para><literal>$JETTY_HOME</literal> refers to the root of your Jetty
|
|
|
|
|
installation.</para>
|
|
|
|
|
|
|
|
|
|
<para>Edit your <literal>$JETTY_HOME/etc/jetty.xml</literal> file so
|
|
|
|
|
the <literal><Configure class></literal> section has a new
|
|
|
|
|
addRealm call:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting> <Call name="addRealm">
|
|
|
|
|
<Arg>
|
|
|
|
|
<New class="net.sf.acegisecurity.adapters.jetty.JettyAcegiUserRealm">
|
|
|
|
|
<Arg>Spring Powered Realm</Arg>
|
|
|
|
|
<Arg>my_password</Arg>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<Arg>etc/acegisecurity.xml</Arg>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</New>
|
|
|
|
|
</Arg>
|
|
|
|
|
</Call></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>Copy <literal>acegisecurity.xml</literal> into
|
|
|
|
|
<literal>$JETTY_HOME/etc</literal>.</para>
|
|
|
|
|
|
|
|
|
|
<para>Copy the following files into
|
|
|
|
|
<literal>$JETTY_HOME/ext</literal>:<itemizedlist>
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>aopalliance.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>commons-logging.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>spring.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>acegi-security-jetty-ext.jar</literal></para>
|
|
|
|
|
</listitem>
|
2004-04-11 12:09:08 +00:00
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>commons-codec.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>burlap.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>hessian.jar</literal></para>
|
|
|
|
|
</listitem>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</itemizedlist></para>
|
|
|
|
|
|
|
|
|
|
<para>None of the above JAR files (or
|
|
|
|
|
<literal>acegi-security.jar</literal>) should be in your application's
|
|
|
|
|
<literal>WEB-INF/lib</literal>. The realm name indicated in your
|
|
|
|
|
<literal>web.xml</literal> does matter with Jetty. The
|
|
|
|
|
<literal>web.xml</literal> must express the same
|
|
|
|
|
<literal><realm-name></literal> as your
|
|
|
|
|
<literal>jetty.xml</literal> (in the example above, "Spring Powered
|
|
|
|
|
Realm").</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-container-adapters-joss">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>JBoss Installation</title>
|
|
|
|
|
|
|
|
|
|
<para>The following was tested with JBoss 3.2.3. We automatically test
|
|
|
|
|
the following directions using our container integration test system
|
|
|
|
|
and this version of JBoss.</para>
|
|
|
|
|
|
|
|
|
|
<para><literal>$JBOSS_HOME</literal> refers to the root of your JBoss
|
|
|
|
|
installation.</para>
|
|
|
|
|
|
|
|
|
|
<para>Edit your
|
|
|
|
|
<literal>$JBOSS_HOME/server/your_config/conf/login-config.xml</literal>
|
|
|
|
|
file so that it contains a new entry under the
|
|
|
|
|
<literal><Policy></literal> section:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting> <application-policy name = "SpringPoweredRealm">
|
|
|
|
|
<authentication>
|
|
|
|
|
<login-module code = "net.sf.acegisecurity.adapters.jboss.JbossSpringLoginModule"
|
|
|
|
|
flag = "required">
|
|
|
|
|
<module-option name = "appContextLocation">acegisecurity.xml</module-option>
|
|
|
|
|
<module-option name = "key">my_password</module-option>
|
|
|
|
|
</login-module>
|
|
|
|
|
</authentication>
|
|
|
|
|
</application-policy></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>Copy <literal>acegisecurity.xml</literal> into
|
|
|
|
|
<literal>$JBOSS_HOME/server/your_config/conf</literal>.</para>
|
|
|
|
|
|
|
|
|
|
<para>Copy the following files into
|
|
|
|
|
<literal>$JBOSS_HOME/server/your_config/lib</literal>:<itemizedlist>
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>aopalliance.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>spring.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>acegi-security-jboss-lib.jar</literal></para>
|
|
|
|
|
</listitem>
|
2004-04-11 12:09:08 +00:00
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>commons-codec.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>burlap.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>hessian.jar</literal></para>
|
|
|
|
|
</listitem>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</itemizedlist></para>
|
|
|
|
|
|
|
|
|
|
<para>None of the above JAR files (or
|
|
|
|
|
<literal>acegi-security.jar</literal>) should be in your application's
|
|
|
|
|
<literal>WEB-INF/lib</literal>. The realm name indicated in your
|
|
|
|
|
<literal>web.xml</literal> does not matter with JBoss. However, your
|
|
|
|
|
web application's <literal>WEB-INF/jboss-web.xml</literal> must
|
|
|
|
|
express the same <literal><security-domain></literal> as your
|
|
|
|
|
<literal>login-config.xml</literal>. For example, to match the above
|
|
|
|
|
example, your <literal>jboss-web.xml</literal> would look like
|
|
|
|
|
this:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting><jboss-web>
|
|
|
|
|
<security-domain>java:/jaas/SpringPoweredRealm</security-domain>
|
|
|
|
|
</jboss-web></programlisting></para>
|
|
|
|
|
</sect2>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<sect2 id="security-container-adapters-resin">
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<title>Resin Installation</title>
|
|
|
|
|
|
|
|
|
|
<para>The following was tested with Resin 3.0.6.</para>
|
|
|
|
|
|
|
|
|
|
<para><literal>$RESIN_HOME</literal> refers to the root of your Resin
|
|
|
|
|
installation.</para>
|
|
|
|
|
|
|
|
|
|
<para>Resin provides several ways to support the container adapter. In
|
|
|
|
|
the instructions below we have elected to maximise consistency with
|
|
|
|
|
other container adapter configurations. This will allow Resin users to
|
|
|
|
|
simply deploy the sample application and confirm correct
|
|
|
|
|
configuration. Developers comfortable with Resin are naturally able to
|
|
|
|
|
use its capabilities to package the JARs with the web application
|
|
|
|
|
itself, and/or support single sign-on.</para>
|
|
|
|
|
|
|
|
|
|
<para>Copy the following files into
|
|
|
|
|
<literal>$RESIN_HOME/lib</literal>:<itemizedlist>
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>aopalliance.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>commons-logging.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>spring.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>acegi-security-resin-lib.jar</literal></para>
|
|
|
|
|
</listitem>
|
2004-04-11 12:09:08 +00:00
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>commons-codec.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>burlap.jar</literal></para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para><literal>hessian.jar</literal></para>
|
|
|
|
|
</listitem>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</itemizedlist></para>
|
|
|
|
|
|
|
|
|
|
<para>Unlike the container-wide <literal>acegisecurity.xml</literal>
|
|
|
|
|
files used by other container adapters, each Resin web application
|
|
|
|
|
will contain its own
|
|
|
|
|
<literal>WEB-INF/resin-acegisecurity.xml</literal> file. Each web
|
|
|
|
|
application will also contain a <literal>resin-web.xml</literal> file
|
|
|
|
|
which Resin uses to start the container adapter:</para>
|
|
|
|
|
|
|
|
|
|
<para><programlisting><web-app>
|
|
|
|
|
<authenticator>
|
|
|
|
|
<type>net.sf.acegisecurity.adapters.resin.ResinAcegiAuthenticator</type>
|
|
|
|
|
<init>
|
|
|
|
|
<app-context-location>WEB-INF/resin-acegisecurity.xml</app-context-location>
|
|
|
|
|
<key>my_password</key>
|
|
|
|
|
</init>
|
|
|
|
|
</authenticator>
|
|
|
|
|
</web-app></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>With the basic configuration provided above, none of the JAR
|
|
|
|
|
files listed (or <literal>acegi-security.jar</literal>) should be in
|
|
|
|
|
your application's <literal>WEB-INF/lib</literal>. The realm name
|
|
|
|
|
indicated in your <literal>web.xml</literal> does not matter with
|
|
|
|
|
Resin, as the relevant authentication class is indicated by the
|
|
|
|
|
<literal><authenticator></literal> setting.</para>
|
|
|
|
|
</sect2>
|
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
|
|
<sect1 id="security-sample">
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<title>Contacts Sample Application</title>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<para>Included with the Acegi Security System for Spring is a very
|
|
|
|
|
simple application that can demonstrate the basic security facilities
|
2004-04-03 05:37:20 +00:00
|
|
|
|
provided by the system (and confirm your Container Adapter is properly
|
|
|
|
|
configured if you're using one).</para>
|
|
|
|
|
|
|
|
|
|
<para>The Contacts sample application includes two deployable versions:
|
|
|
|
|
<literal>contacts.war</literal> is configured with the HTTP Session
|
|
|
|
|
Authentication approach, and does not use Container Adapters. The
|
|
|
|
|
<literal>contacts-container-adapter.war</literal> is configured to use a
|
|
|
|
|
Container Adapter. If you're just wanting to see how the sample
|
|
|
|
|
application works, please use <literal>contacts.war</literal> as it does
|
|
|
|
|
not require special configuration of your container.</para>
|
|
|
|
|
|
|
|
|
|
<para>If you are going to use the
|
|
|
|
|
<literal>contacts-container-adapter.war</literal> version, first
|
|
|
|
|
configure your container as described in the Container Adapters section
|
|
|
|
|
of this chapter. Do not modify <literal>acegisecurity.xml</literal>. It
|
|
|
|
|
contains a very basic in-memory authentication configuration that is
|
|
|
|
|
compatible with the sample application.</para>
|
|
|
|
|
|
|
|
|
|
<para>To deploy, simply copy the relevant
|
|
|
|
|
<literal>contacts.war</literal> or
|
|
|
|
|
<literal>contacts-container-adapter.war</literal> file from the Acegi
|
|
|
|
|
Security System for Spring distribution into your container’s
|
2004-03-16 23:57:17 +00:00
|
|
|
|
<literal>webapps</literal> directory.</para>
|
|
|
|
|
|
|
|
|
|
<para>After starting your container, check the application can load.
|
|
|
|
|
Visit <literal>http://localhost:8080/contacts</literal> (or whichever
|
2004-04-03 05:37:20 +00:00
|
|
|
|
URL is appropriate for your web container and the WAR you deployed). A
|
|
|
|
|
random contact should be displayed. Click "Refresh" several times and
|
|
|
|
|
you will see different contacts. The business method that provides this
|
|
|
|
|
random contact is not secured.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<para>Next, click "Debug". You will be prompted to authenticate, and a
|
|
|
|
|
series of usernames and passwords are suggested on that page. Simply
|
|
|
|
|
authenticate with any of these and view the resulting page. It should
|
|
|
|
|
contain a success message similar to the following:</para>
|
|
|
|
|
|
|
|
|
|
<blockquote>
|
|
|
|
|
<para>Context on ContextHolder is of type:
|
|
|
|
|
net.sf.acegisecurity.context.SecureContextImpl</para>
|
|
|
|
|
|
|
|
|
|
<para>The Context implements SecureContext.</para>
|
|
|
|
|
|
|
|
|
|
<para>Authentication object is of type:
|
|
|
|
|
net.sf.acegisecurity.adapters.PrincipalAcegiUserToken</para>
|
|
|
|
|
|
|
|
|
|
<para>Authentication object as a String:
|
|
|
|
|
net.sf.acegisecurity.adapters.PrincipalAcegiUserToken@e9a7c2:
|
|
|
|
|
Username: marissa; Password: [PROTECTED]; Authenticated: true; Granted
|
|
|
|
|
Authorities: ROLE_TELLER, ROLE_SUPERVISOR</para>
|
|
|
|
|
|
|
|
|
|
<para>Authentication object holds the following granted
|
|
|
|
|
authorities:</para>
|
|
|
|
|
|
|
|
|
|
<para>ROLE_TELLER (getAuthority(): ROLE_TELLER)</para>
|
|
|
|
|
|
|
|
|
|
<para>ROLE_SUPERVISOR (getAuthority(): ROLE_SUPERVISOR)</para>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>SUCCESS! Your [container adapter|web filter] appears to be
|
|
|
|
|
properly configured!</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</blockquote>
|
|
|
|
|
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>If you receive a different message, and deployed
|
|
|
|
|
<literal>contacts-container-adapter.war</literal>, check you have
|
|
|
|
|
properly configured your Container Adapter. Refer to the instructions
|
|
|
|
|
provided above.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
|
|
|
|
|
<para>Once you successfully receive the above message, return to the
|
|
|
|
|
sample application's home page and click "Manage". You can then try out
|
|
|
|
|
the application. Notice that only the contacts belonging to the
|
|
|
|
|
currently logged on user are displayed, and only users with
|
|
|
|
|
<literal>ROLE_SUPERVISOR</literal> are granted access to delete their
|
2004-04-03 05:37:20 +00:00
|
|
|
|
contacts. Behind the scenes, the
|
|
|
|
|
<literal>MethodSecurityInterceptor</literal> is securing the business
|
|
|
|
|
objects. If you're using <literal>contacts.war</literal>, the
|
|
|
|
|
<literal>FilterSecurityInterceptor</literal> is also securing the HTTP
|
|
|
|
|
requests. If using <literal>contacts.war</literal>, be sure to try
|
|
|
|
|
visiting <literal>http://localhost:8080/contacts/secure/super</literal>,
|
|
|
|
|
which will demonstrate access being denied by the
|
|
|
|
|
<literal>SecurityEnforcementFilter</literal>.</para>
|
2004-04-11 12:09:08 +00:00
|
|
|
|
|
|
|
|
|
<para>The Contacts sample application also include a
|
|
|
|
|
<literal>client</literal> directory. Inside you will find a small
|
|
|
|
|
application that queries the backend business objects using the Hessian
|
|
|
|
|
and Burlap protocols. This demonstrates how to use the Acegi Security
|
|
|
|
|
System for Spring for authentication with Spring remoting protocols. To
|
|
|
|
|
try this client, ensure your servlet container is still running the
|
2004-04-11 13:14:19 +00:00
|
|
|
|
Contacts sample application, and then execute <literal>client marissa
|
|
|
|
|
marissa koala</literal>. The command-line parameters respectively
|
|
|
|
|
represent the owner of the contacts to extract, the username to use, and
|
|
|
|
|
the password to use. Note that you may need to edit
|
|
|
|
|
<literal>client.properties</literal> to use a different target URL. To
|
|
|
|
|
see that security does indeed work, try running <literal>client scott
|
|
|
|
|
marissa koala</literal>, which will try to obtain
|
|
|
|
|
<literal>scott</literal>'s contacts when authenticating as
|
|
|
|
|
<literal>marissa</literal>. To see it work properly, use <literal>client
|
|
|
|
|
scott scott wombat</literal>.</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
|
|
<sect1 id="security-become-involved">
|
|
|
|
|
<title>Become Involved</title>
|
|
|
|
|
|
|
|
|
|
<para>We welcome you to become involved in the Acegi Security System for
|
|
|
|
|
Spring project. There are many ways of contributing, including reading
|
|
|
|
|
the mailing list and responding to questions from other people, writing
|
|
|
|
|
new code, improving existing code, assisting with documentation, or
|
|
|
|
|
simply making suggestions.</para>
|
|
|
|
|
|
|
|
|
|
<para>SourceForge provides CVS services for the project, allowing
|
|
|
|
|
anybody to access the latest code. If you wish to contribute new code,
|
|
|
|
|
please observe the following requirements. These exist to maintain the
|
|
|
|
|
quality and consistency of the project:</para>
|
|
|
|
|
|
|
|
|
|
<itemizedlist>
|
|
|
|
|
<listitem>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>Run the Ant <literal>format</literal> task (or use a suitable
|
|
|
|
|
IDE plug-in) to convert your code into the project's consistent
|
|
|
|
|
style</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Ensure your code does not break any unit tests (run the Ant
|
|
|
|
|
<literal>tests</literal> target)</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Please use the container integration test system to test your
|
|
|
|
|
code in the project's officially supported containers</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>When writing a new container adapter, expand the container
|
|
|
|
|
integration test system to properly test it</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>If you have added new code, please provide suitable unit tests
|
|
|
|
|
(use <literal>ant clover.html</literal> to view coverage)</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
<listitem>
|
2004-04-03 05:37:20 +00:00
|
|
|
|
<para>Add a CVS <literal>$Id: index.xml,v 1.3 2004/04/02 21:12:25
|
|
|
|
|
fbos Exp $</literal> tag to the JavaDocs for any new class you
|
|
|
|
|
create</para>
|
2004-03-16 23:57:17 +00:00
|
|
|
|
</listitem>
|
|
|
|
|
</itemizedlist>
|
|
|
|
|
|
|
|
|
|
<para>Mentioned above is our container integration test system, which
|
|
|
|
|
aims to test the Acegi Security System for Spring container adapters
|
|
|
|
|
with current, production versions of each container. Some containers
|
|
|
|
|
might not be supported due to difficulties with starting or stopping the
|
|
|
|
|
container within an Ant target. You will need to download the container
|
|
|
|
|
release files as specified in the integration test
|
|
|
|
|
<literal>readme.txt</literal> file. These files are intentionally
|
|
|
|
|
excluded from CVS due to their large size.</para>
|
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
|
|
<sect1 id="security-further">
|
|
|
|
|
<title>Further Information</title>
|
|
|
|
|
|
|
|
|
|
<para>Questions and comments on the Acegi Security System for Spring are
|
|
|
|
|
welcome. Please direct comments to the Spring Users mailing list or
|
|
|
|
|
ben.alex@acegi.com.au. Our project home page (where you can obtain the
|
|
|
|
|
latest release of the project and access to CVS) is at
|
|
|
|
|
<literal>http://acegisecurity.sourceforge.net</literal>.</para>
|
|
|
|
|
</sect1>
|
|
|
|
|
</chapter>
|
|
|
|
|
</book>
|