Remove ContextHolder and introduce SecurityContext.
This commit is contained in:
@@ -326,115 +326,67 @@
|
||||
<sect1 id="security-request-contexts">
|
||||
<title>Request Contexts</title>
|
||||
|
||||
<sect2 id="security-contexts">
|
||||
<title>Contexts</title>
|
||||
<sect2 id="security-contexts-history">
|
||||
<title>Historical Approach</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><mediaobject>
|
||||
<imageobject role="html">
|
||||
<imagedata align="center" fileref="images/Context.gif"
|
||||
format="GIF" />
|
||||
</imageobject>
|
||||
|
||||
<caption>
|
||||
<para>Figure 2: The ContextHolder</para>
|
||||
</caption>
|
||||
</mediaobject></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>
|
||||
<para>Prior to release 0.9.0, Acegi Security used a
|
||||
<literal>ContextHolder</literal> to store a <literal>Context</literal>
|
||||
between sessions. A particular subclass of <literal>Context</literal>,
|
||||
<literal>SecureContext</literal> defined an interface used for storage
|
||||
of the <literal>Authentication</literal> object. The
|
||||
<literal>ContextHolder</literal> was a <literal>ThreadLocal</literal>.
|
||||
This was removed from 0.9.0 after discussion with other Spring
|
||||
developers for the sake of consistency. See for example
|
||||
<literal>http://article.gmane.org/gmane.comp.java.springframework.devel/8290</literal>.
|
||||
This history is mentioned as the long period
|
||||
<literal>ContextHolder</literal> was used will likely mean that
|
||||
certain documentation you encounter concerning Acegi Security might
|
||||
still refer to <literal>ContextHolder</literal>. Generally you can
|
||||
just substitute "<literal>SecurityContext</literal>" for
|
||||
"<literal>ContextHolder</literal>" and you'll have the primary meaning
|
||||
of such documentation.</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="security-contexts-secure-contexts">
|
||||
<title>Secure Contexts</title>
|
||||
<sect2 id="security-contexts-security-context">
|
||||
<title>SecurityContext</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>
|
||||
<para>The Acegi Security System for Spring uses a
|
||||
<literal>SecurityContext</literal> to store the
|
||||
<literal>Authentication</literal>. All Acegi Security classes query
|
||||
the <literal>SecurityContext</literal> for obtaining the currently
|
||||
principal. <literal>SecurityContext</literal> is an
|
||||
<literal>InheritableThreadLocal</literal>, meaning it is associated
|
||||
with the current thread of execution.
|
||||
<literal>SecurityContext</literal> simply provides a single getter and
|
||||
setter pair for the <literal>Authentication</literal> object.</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="security-contexts-storage">
|
||||
<title>Context Storage</title>
|
||||
|
||||
<para>Central to Acegi Security's design is that the contents of the
|
||||
<literal>ContextHolder</literal> (ie the <literal>Context</literal>)
|
||||
can be stored between web requests. This is so that a successfully
|
||||
authenticated principal can be identified on subsequent requests
|
||||
through the <literal>Authentication</literal> stored inside a
|
||||
<literal>SecureContext</literal> implementation. The
|
||||
<literal>SecurityContext</literal> (which is simply an
|
||||
<literal>Authentication</literal> object) can be stored between web
|
||||
requests. This is so that a successfully authenticated principal can
|
||||
be identified on subsequent requests through the
|
||||
<literal>Authentication</literal> stored inside a
|
||||
<literal>SecurityContext</literal>. The
|
||||
<literal>HttpSessionContextIntegrationFilter</literal> exists to
|
||||
automatically copy the contents of a well-defined
|
||||
<literal>HttpSession</literal> attribute into the
|
||||
<literal>ContextHolder</literal>, then at the end of each request,
|
||||
copy the <literal>ContextHolder</literal> contents back into the
|
||||
<literal>SecurityContext</literal>, then at the end of each request,
|
||||
copy the <literal>SecurityContext</literal> contents back into the
|
||||
<literal>HttpSession</literal> ready for next request.</para>
|
||||
|
||||
<para>It is essential - and an extremely common error of end users -
|
||||
that <literal>HttpSessionContextIntegrationFilter</literal> appears
|
||||
before any other Acegi Security filter. This is because other Acegi
|
||||
Security filters (along with all Acegi Security classes) expect the
|
||||
<literal>ContextHolder</literal> to contain a valid
|
||||
<literal>SecureContext</literal> by the time they are called. Acegi
|
||||
Security filters also expect to be able to modify the
|
||||
<literal>ContextHolder</literal> contents as they see fit, and
|
||||
something else will store those between requests if necessary. This is
|
||||
why <literal>HttpSessionContextIntegrationFilter</literal> must be the
|
||||
before any other Acegi Security filter. Acegi Security filters expect
|
||||
to be able to modify the <literal>SecurityContext</literal> contents
|
||||
as they see fit, and something else (namely
|
||||
<literal>HttpSessionContextIntegrationFilter</literal>) will store
|
||||
those between requests if necessary. This is why
|
||||
<literal>HttpSessionContextIntegrationFilter</literal> must be the
|
||||
first filter used.</para>
|
||||
|
||||
<para>The <literal>HttpSessionContextIntegrationFilter</literal> has
|
||||
been designed to store all types of <literal>Context</literal> objects
|
||||
- not merely Acegi Security related contexts. This means, for example,
|
||||
that you can extend <literal>SecureContextImpl</literal> to store a
|
||||
locale or some other parameter, and
|
||||
<literal>HttpSessionContextIntegrationFilter</literal> will
|
||||
automatically manage it between web requests.</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
</properties>
|
||||
<body>
|
||||
<release version="0.9.0" date="In CVS">
|
||||
<action dev="benalex" type="update">ContextHolder and related classes removed and replaced with SecurityContext</action>
|
||||
<action dev="luke_t" type="update">Changed order of credentials verification and expiry checking in DaoAuthenticationProvider. Password must now be successfully verified before expired credentials are reported. </action>
|
||||
<action dev="benalex" type="update">AnonymousProcessingFilter offers protected method to control when it should execute</action>
|
||||
<action dev="benalex" type="fix">AbstractAuthenticationToken.getName() now returns username alone if UserDetails present</action>
|
||||
|
||||
46
doc/xdocs/upgrade/upgrade-080-090.html
Normal file
46
doc/xdocs/upgrade/upgrade-080-090.html
Normal file
@@ -0,0 +1,46 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Acegi Security - Upgrading from version 0.8.0 to 1.0.0</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Upgrading from 0.8.0 to 1.0.0</h1>
|
||||
|
||||
<p>
|
||||
The following should help most casual users of the project update their
|
||||
applications:
|
||||
|
||||
<ul>
|
||||
|
||||
<li>The most significant change in 0.9.0 is that <code>ContextHolder</code> and all of its
|
||||
related classes have been removed. This significant change was made for the sake of consistency
|
||||
with the core Spring project's approach of a single <code>ThreadLocal</code> per use case,
|
||||
instead of a shared <code>ThreadLocal</code> for multiple use cases as the previous
|
||||
<code>ContextHolder</code> allowed. <b>This is an important change in 0.9.0.</b> Many applications
|
||||
will need to modify their code (and possibly web views) if they directly interact with the old
|
||||
<code>ContextHolder</code>. The replacement security <code>ThreadLocal</code> is called
|
||||
<a href="../multiproject/acegi-security/xref/net/sf/acegisecurity/context/SecurityContext.html">
|
||||
SecurityContext</a> and provides a single getter/setter for <code>Authentication</code>. There is
|
||||
thus no need to work with <code>SecureContext</code> or <code>Context</code> anymore. <BR><BR>
|
||||
|
||||
To migrate, simply modify all your code that previously worked with <code>ContextHolder</code>,
|
||||
<code>SecureContext</code> and <code>Context</code> to directly call <code>SecurityContext</code>.
|
||||
You will also note that the <code>HttpSessionContextIntegrationFilter</code> no longer provides
|
||||
a <code>context</code> property, so remove it from your application context XML. For the relatively
|
||||
small number of users who had customised their context, you will need to write your own
|
||||
<code>ThreadLocal</code> to provide functionality for your specific use case.<BR><BR>
|
||||
|
||||
We apologise for the inconvenience, but on a more positive note this means you receive strict
|
||||
type checking, you no longer need to mess around with casting to and from <code>Context</code>
|
||||
implementations, your applications no longer need to perform checking of <code>null</code> and
|
||||
unexpected <code>Context</code> implementation types, and the new <code>SecurityContext</code>
|
||||
is an <code>InheritableThreadLocal</code> - which should make life easier in rich client
|
||||
environments.<br><br></li>
|
||||
|
||||
<li>AbstractProcessingFilter has changed its getter/setter approach used for customised
|
||||
authentication exception directions. See the <a href="../multiproject/acegi-security/xref/net/sf/acegisecurity/ui/AbstractProcessingFilter.html">
|
||||
AbstractProcessingFilter JavaDocs</a> to learn more.<br><br></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,21 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Acegi Security - Upgrading from version 0.8.0 to 1.0.0</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Upgrading from 0.8.0 to 1.0.0</h1>
|
||||
|
||||
<p>
|
||||
The following should help most casual users of the project update their
|
||||
applications:
|
||||
|
||||
<ul>
|
||||
|
||||
<li>AbstractProcessingFilter has changed its getter/setter approach used for customised
|
||||
authentication exception directions. See the <a href="../multiproject/acegi-security/xref/net/sf/acegisecurity/ui/AbstractProcessingFilter.html">
|
||||
AbstractProcessingFilter JavaDocs</a> to learn more.<br><br></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user