Minor doc updates
This commit is contained in:
parent
0a37aed4b9
commit
40efe6db57
|
@ -1,293 +1,244 @@
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="authorization-common" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="authorization-common"
|
||||||
<info><title>Common Authorization Concepts</title></info>
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<info>
|
||||||
|
<title>Common Authorization Concepts</title>
|
||||||
|
</info>
|
||||||
<section xml:id="authorities">
|
<section xml:id="authorities">
|
||||||
<info><title>Authorities</title></info>
|
<info>
|
||||||
|
<title>Authorities</title>
|
||||||
<para>As briefly mentioned in the Authentication section, all
|
</info>
|
||||||
<interfacename>Authentication</interfacename> implementations are required to
|
<para>As we saw in the <link xlink:href="#tech-granted-authority">technical overview</link>, all
|
||||||
store an array of <interfacename>GrantedAuthority</interfacename> objects. These
|
<interfacename>Authentication</interfacename> implementations store a list of
|
||||||
represent the authorities that have been granted to the principal. The
|
<interfacename>GrantedAuthority</interfacename> objects. These represent the authorities
|
||||||
<interfacename>GrantedAuthority</interfacename> objects are inserted into the
|
that have been granted to the principal. The <interfacename>GrantedAuthority</interfacename>
|
||||||
<interfacename>Authentication</interfacename> object by the
|
objects are inserted into the <interfacename>Authentication</interfacename> object by the
|
||||||
<interfacename>AuthenticationManager</interfacename> and are later read by
|
<interfacename>AuthenticationManager</interfacename> and are later read by
|
||||||
<interfacename>AccessDecisionManager</interfacename>s when making authorization
|
<interfacename>AccessDecisionManager</interfacename>s when making authorization
|
||||||
decisions.</para>
|
decisions.</para>
|
||||||
|
<para><interfacename>GrantedAuthority</interfacename> is an interface with only one method:
|
||||||
<para><interfacename>GrantedAuthority</interfacename> is an interface with only
|
|
||||||
one method:
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
String getAuthority();
|
String getAuthority();
|
||||||
</programlisting>
|
</programlisting> This method allows
|
||||||
This method allows <interfacename>AccessDecisionManager</interfacename>s to
|
<interfacename>AccessDecisionManager</interfacename>s to obtain a precise
|
||||||
obtain a precise <literal>String</literal> representation of the
|
<literal>String</literal> representation of the
|
||||||
<interfacename>GrantedAuthority</interfacename>. By returning a representation as
|
<interfacename>GrantedAuthority</interfacename>. By returning a representation as a
|
||||||
a <literal>String</literal>, a <interfacename>GrantedAuthority</interfacename> can
|
<literal>String</literal>, a <interfacename>GrantedAuthority</interfacename> can be easily
|
||||||
be easily "read" by most <interfacename>AccessDecisionManager</interfacename>s. If
|
<quote>read</quote> by most <interfacename>AccessDecisionManager</interfacename>s. If a
|
||||||
a <interfacename>GrantedAuthority</interfacename> cannot be precisely represented
|
<interfacename>GrantedAuthority</interfacename> cannot be precisely represented as a
|
||||||
as a <literal>String</literal>, the
|
<literal>String</literal>, the <interfacename>GrantedAuthority</interfacename> is considered
|
||||||
<interfacename>GrantedAuthority</interfacename> is considered "complex" and
|
<quote>complex</quote> and <literal>getAuthority()</literal> must return
|
||||||
<literal>getAuthority()</literal> must return
|
<literal>null</literal>.</para>
|
||||||
<literal>null</literal>.</para>
|
<para>An example of a <quote>complex</quote>
|
||||||
|
<interfacename>GrantedAuthority</interfacename> would be an implementation that stores a list
|
||||||
<para>An example of a "complex" <interfacename>GrantedAuthority</interfacename>
|
of operations and authority thresholds that apply to different customer account numbers.
|
||||||
would be an implementation that stores a list of operations and
|
Representing this complex <interfacename>GrantedAuthority</interfacename> as a
|
||||||
authority thresholds that apply to different customer account numbers.
|
<literal>String</literal> would be quite difficult, and as a result the
|
||||||
Representing this complex <interfacename>GrantedAuthority</interfacename> as a
|
<literal>getAuthority()</literal> method should return <literal>null</literal>. This will
|
||||||
<literal>String</literal> would be quite complex, and as a result the
|
indicate to any <interfacename>AccessDecisionManager</interfacename> that it will need to
|
||||||
<literal>getAuthority()</literal> method should return
|
specifically support the <interfacename>GrantedAuthority</interfacename> implementation in
|
||||||
<literal>null</literal>. This will indicate to any
|
order to understand its contents.</para>
|
||||||
<interfacename>AccessDecisionManager</interfacename> that it will need to
|
<para>Spring Security includes one concrete <interfacename>GrantedAuthority</interfacename>
|
||||||
specifically support the <interfacename>GrantedAuthority</interfacename>
|
implementation, <literal>GrantedAuthorityImpl</literal>. This allows any user-specified
|
||||||
implementation in order to understand its contents.</para>
|
<literal>String</literal> to be converted into a
|
||||||
|
<interfacename>GrantedAuthority</interfacename>. All
|
||||||
<para>Spring Security includes one concrete
|
<classname>AuthenticationProvider</classname>s included with the security architecture use
|
||||||
<interfacename>GrantedAuthority</interfacename> implementation,
|
<literal>GrantedAuthorityImpl</literal> to populate the
|
||||||
<literal>GrantedAuthorityImpl</literal>. This allows any
|
<interfacename>Authentication</interfacename> object.</para>
|
||||||
user-specified <literal>String</literal> to be converted into a
|
|
||||||
<interfacename>GrantedAuthority</interfacename>. All
|
|
||||||
<classname>AuthenticationProvider</classname>s included with the security
|
|
||||||
architecture use <literal>GrantedAuthorityImpl</literal> to populate
|
|
||||||
the <interfacename>Authentication</interfacename> object.</para>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="pre-invocation">
|
<section xml:id="pre-invocation">
|
||||||
<info>
|
<info>
|
||||||
<title>Pre-Invocation Handling</title>
|
<title>Pre-Invocation Handling</title>
|
||||||
</info>
|
</info>
|
||||||
<para>
|
<para> As we've also seen in the <link xlink:href="#secure-objects">Technical Overview</link>
|
||||||
As we'll see in the <link xlink:href="#secure-objects" >Technical Overview</link> chapter, Spring
|
chapter, Spring Security provides interceptors which control access to secure objects such as
|
||||||
Security provides interceptors which control access to secure objects such as method invocations
|
method invocations or web requests. A pre-invocation decision on whether the invocation is
|
||||||
or web requests. A pre-invocation decision on whether the invocation is allowed to proceed is made by
|
allowed to proceed is made by the <interfacename>AccessDecisionManager</interfacename>. </para>
|
||||||
the <interfacename>AccessDecisionManager</interfacename>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<title>The AccessDecisionManager</title>
|
<title>The AccessDecisionManager</title>
|
||||||
<para>The <interfacename>AccessDecisionManager</interfacename> is called by the
|
<para>The <interfacename>AccessDecisionManager</interfacename> is called by the
|
||||||
<classname>AbstractSecurityInterceptor</classname> and is responsible for
|
<classname>AbstractSecurityInterceptor</classname> and is responsible for making final
|
||||||
making final access control decisions. The
|
access control decisions. The <interfacename>AccessDecisionManager</interfacename> interface
|
||||||
<interfacename>AccessDecisionManager</interfacename> interface contains three
|
contains three methods:
|
||||||
methods:
|
<programlisting>
|
||||||
<programlisting>
|
|
||||||
void decide(Authentication authentication, Object secureObject,
|
void decide(Authentication authentication, Object secureObject,
|
||||||
List<ConfigAttribute> config) throws AccessDeniedException;
|
List<ConfigAttribute> config) throws AccessDeniedException;
|
||||||
boolean supports(ConfigAttribute attribute);
|
boolean supports(ConfigAttribute attribute);
|
||||||
boolean supports(Class clazz);
|
boolean supports(Class clazz);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
As can be seen from the first method, the
|
The <interfacename>AccessDecisionManager</interfacename>'s <methodname>decide</methodname>
|
||||||
<interfacename>AccessDecisionManager</interfacename> is passed via method
|
method is passed all the relevant information it needs in order to make an authorization
|
||||||
parameters all information that is likely to be of value in assessing
|
decision. In particular, passing the secure <literal>Object</literal> enables those
|
||||||
an authorization decision. In particular, passing the secure
|
arguments contained in the actual secure object invocation to be inspected. For example,
|
||||||
<literal>Object</literal> enables those arguments contained in the
|
let's assume the secure object was a <classname>MethodInvocation</classname>. It would be
|
||||||
actual secure object invocation to be inspected. For example, let's
|
easy to query the <classname>MethodInvocation</classname> for any
|
||||||
assume the secure object was a <classname>MethodInvocation</classname>. It
|
<literal>Customer</literal> argument, and then implement some sort of security logic in
|
||||||
would be easy to query the <classname>MethodInvocation</classname> for any
|
the <interfacename>AccessDecisionManager</interfacename> to ensure the principal is
|
||||||
<literal>Customer</literal> argument, and then implement some sort of
|
permitted to operate on that customer. Implementations are expected to throw an
|
||||||
security logic in the <interfacename>AccessDecisionManager</interfacename> to
|
<literal>AccessDeniedException</literal> if access is denied.</para>
|
||||||
ensure the principal is permitted to operate on that customer.
|
<para>The <literal>supports(ConfigAttribute)</literal> method is called by the
|
||||||
Implementations are expected to throw an
|
<classname>AbstractSecurityInterceptor</classname> at startup time to determine if the
|
||||||
<literal>AccessDeniedException</literal> if access is denied.</para>
|
<interfacename>AccessDecisionManager</interfacename> can process the passed
|
||||||
|
<literal>ConfigAttribute</literal>. The <literal>supports(Class)</literal> method is
|
||||||
<para>The <literal>supports(ConfigAttribute)</literal> method is
|
called by a security interceptor implementation to ensure the configured
|
||||||
called by the <classname>AbstractSecurityInterceptor</classname> at
|
<interfacename>AccessDecisionManager</interfacename> supports the type of secure object
|
||||||
startup time to determine if the
|
that the security interceptor will present.</para>
|
||||||
<interfacename>AccessDecisionManager</interfacename> can process the passed
|
<section>
|
||||||
<literal>ConfigAttribute</literal>. The
|
<title>Voting-Based AccessDecisionManager Implementations</title>
|
||||||
<literal>supports(Class)</literal> method is called by a security
|
<para>Whilst users can implement their own
|
||||||
interceptor implementation to ensure the configured
|
<interfacename>AccessDecisionManager</interfacename> to control all aspects of
|
||||||
<interfacename>AccessDecisionManager</interfacename> supports the type of secure
|
authorization, Spring Security includes several
|
||||||
object that the security interceptor will present.</para>
|
<interfacename>AccessDecisionManager</interfacename> implementations that are based on
|
||||||
|
voting. <xref linkend="authz-access-voting"/> illustrates the relevant classes.</para>
|
||||||
<section>
|
<figure xml:id="authz-access-voting">
|
||||||
<title>Voting-Based AccessDecisionManager Implementations</title>
|
<title>Voting Decision Manager</title>
|
||||||
<para>Whilst users can implement their own <interfacename>AccessDecisionManager</interfacename> to control all aspects of
|
<mediaobject>
|
||||||
authorization, Spring Security includes several <interfacename>AccessDecisionManager</interfacename> implementations that are
|
<!--
|
||||||
based on voting. <xref linkend="authz-access-voting"/> illustrates the relevant classes.</para>
|
|
||||||
<figure xml:id="authz-access-voting">
|
|
||||||
<title>Voting Decision Manager</title>
|
|
||||||
<mediaobject>
|
|
||||||
<!--
|
|
||||||
<imageobject role="fo">
|
<imageobject role="fo">
|
||||||
<imagedata align="center" fileref="resources/images/AccessDecisionVoting.gif" format="GIF"/>
|
<imagedata align="center" fileref="resources/images/AccessDecisionVoting.gif" format="GIF"/>
|
||||||
</imageobject>
|
</imageobject>
|
||||||
-->
|
-->
|
||||||
<imageobject>
|
<imageobject>
|
||||||
<imagedata align="center" scalefit="1" fileref="images/AccessDecisionVoting.gif" format="GIF"/>
|
<imagedata align="center" scalefit="1" fileref="images/AccessDecisionVoting.gif"
|
||||||
</imageobject>
|
format="GIF"/>
|
||||||
</mediaobject>
|
</imageobject>
|
||||||
</figure>
|
</mediaobject>
|
||||||
<para>Using this approach, a series of
|
</figure>
|
||||||
<interfacename>AccessDecisionVoter</interfacename> implementations are polled on
|
<para>Using this approach, a series of <interfacename>AccessDecisionVoter</interfacename>
|
||||||
an authorization decision. The
|
implementations are polled on an authorization decision. The
|
||||||
<interfacename>AccessDecisionManager</interfacename> then decides whether or not
|
<interfacename>AccessDecisionManager</interfacename> then decides whether or not to
|
||||||
to throw an <literal>AccessDeniedException</literal> based on its
|
throw an <literal>AccessDeniedException</literal> based on its assessment of the
|
||||||
assessment of the votes.</para>
|
votes.</para>
|
||||||
|
<para>The <interfacename>AccessDecisionVoter</interfacename> interface has three methods:
|
||||||
<para>The <interfacename>AccessDecisionVoter</interfacename> interface has three
|
<programlisting>
|
||||||
methods:
|
|
||||||
<programlisting>
|
|
||||||
int vote(Authentication authentication, Object object, List<ConfigAttribute> config);
|
int vote(Authentication authentication, Object object, List<ConfigAttribute> config);
|
||||||
boolean supports(ConfigAttribute attribute);
|
boolean supports(ConfigAttribute attribute);
|
||||||
boolean supports(Class clazz);
|
boolean supports(Class clazz);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
Concrete implementations return an <literal>int</literal>, with
|
Concrete implementations return an <literal>int</literal>, with possible values being
|
||||||
possible values being reflected in the
|
reflected in the <interfacename>AccessDecisionVoter</interfacename> static fields
|
||||||
<interfacename>AccessDecisionVoter</interfacename> static fields
|
<literal>ACCESS_ABSTAIN</literal>, <literal>ACCESS_DENIED</literal> and
|
||||||
<literal>ACCESS_ABSTAIN</literal>, <literal>ACCESS_DENIED</literal>
|
<literal>ACCESS_GRANTED</literal>. A voting implementation will return
|
||||||
and <literal>ACCESS_GRANTED</literal>. A voting implementation will
|
<literal>ACCESS_ABSTAIN</literal> if it has no opinion on an authorization decision. If
|
||||||
return <literal>ACCESS_ABSTAIN</literal> if it has no opinion on an
|
it does have an opinion, it must return either <literal>ACCESS_DENIED</literal> or
|
||||||
authorization decision. If it does have an opinion, it must return
|
<literal>ACCESS_GRANTED</literal>.</para>
|
||||||
either <literal>ACCESS_DENIED</literal> or
|
<para>There are three concrete <interfacename>AccessDecisionManager</interfacename>s
|
||||||
<literal>ACCESS_GRANTED</literal>.</para>
|
provided with Spring Security that tally the votes. The <literal>ConsensusBased</literal>
|
||||||
|
implementation will grant or deny access based on the consensus of non-abstain votes.
|
||||||
<para>There are three concrete
|
Properties are provided to control behavior in the event of an equality of votes or if all
|
||||||
<interfacename>AccessDecisionManager</interfacename>s provided with Spring
|
votes are abstain. The <literal>AffirmativeBased</literal> implementation will grant
|
||||||
Security that tally the votes. The <literal>ConsensusBased</literal>
|
access if one or more <literal>ACCESS_GRANTED</literal> votes were received (i.e. a deny
|
||||||
implementation will grant or deny access based on the consensus of
|
vote will be ignored, provided there was at least one grant vote). Like the
|
||||||
non-abstain votes. Properties are provided to control behavior in the
|
<literal>ConsensusBased</literal> implementation, there is a parameter that controls the
|
||||||
event of an equality of votes or if all votes are abstain. The
|
behavior if all voters abstain. The <literal>UnanimousBased</literal> provider expects
|
||||||
<literal>AffirmativeBased</literal> implementation will grant access
|
unanimous <literal>ACCESS_GRANTED</literal> votes in order to grant access, ignoring
|
||||||
if one or more <literal>ACCESS_GRANTED</literal> votes were received
|
abstains. It will deny access if there is any <literal>ACCESS_DENIED</literal> vote. Like
|
||||||
(i.e. a deny vote will be ignored, provided there was at least one grant
|
the other implementations, there is a parameter that controls the behaviour if all voters
|
||||||
vote). Like the <literal>ConsensusBased</literal> implementation,
|
abstain.</para>
|
||||||
there is a parameter that controls the behavior if all voters abstain.
|
<para>It is possible to implement a custom
|
||||||
The <literal>UnanimousBased</literal> provider expects unanimous
|
<interfacename>AccessDecisionManager</interfacename> that tallies votes differently. For
|
||||||
<literal>ACCESS_GRANTED</literal> votes in order to grant access,
|
example, votes from a particular <interfacename>AccessDecisionVoter</interfacename> might
|
||||||
ignoring abstains. It will deny access if there is any
|
receive additional weighting, whilst a deny vote from a particular voter may have a veto
|
||||||
<literal>ACCESS_DENIED</literal> vote. Like the other implementations,
|
effect.</para>
|
||||||
there is a parameter that controls the behaviour if all voters
|
<section>
|
||||||
abstain.</para>
|
<title><classname>RoleVoter</classname></title>
|
||||||
|
<para> The most commonly used <interfacename>AccessDecisionVoter</interfacename> provided
|
||||||
<para>It is possible to implement a custom
|
with Spring Security is the simple <classname>RoleVoter</classname>, which treats
|
||||||
<interfacename>AccessDecisionManager</interfacename> that tallies votes
|
configuration attributes as simple role names and votes to grant access if the user has
|
||||||
differently. For example, votes from a particular
|
been assigned that role.</para>
|
||||||
<interfacename>AccessDecisionVoter</interfacename> might receive additional
|
<para>It will vote if any ConfigAttribute begins with the prefix <literal>ROLE_</literal>.
|
||||||
weighting, whilst a deny vote from a particular voter may have a veto
|
It will vote to grant access if there is a
|
||||||
effect.</para>
|
<interfacename>GrantedAuthority</interfacename> which returns a
|
||||||
|
<literal>String</literal> representation (via the <literal>getAuthority()</literal>
|
||||||
<section>
|
method) exactly equal to one or more <literal>ConfigAttributes</literal> starting with
|
||||||
<title><classname>RoleVoter</classname></title>
|
<literal>ROLE_</literal>. If there is no exact match of any
|
||||||
<para>
|
<literal>ConfigAttribute</literal> starting with <literal>ROLE_</literal>, the
|
||||||
The most commonly used <interfacename>AccessDecisionVoter</interfacename>
|
<literal>RoleVoter</literal> will vote to deny access. If no
|
||||||
provided with Spring Security is the simple <classname>RoleVoter</classname>, which treats
|
<literal>ConfigAttribute</literal> begins with <literal>ROLE_</literal>, the voter
|
||||||
configuration attributes as simple role names and votes to grant access if the user has been assigned
|
will abstain. <literal>RoleVoter</literal> is case sensitive on comparisons as well as
|
||||||
that role.</para>
|
the <literal>ROLE_</literal> prefix.</para>
|
||||||
<para>It will vote if any ConfigAttribute begins with the prefix <literal>ROLE_</literal>.
|
</section>
|
||||||
It will vote to grant access if there is a <interfacename>GrantedAuthority</interfacename> which returns a
|
<section>
|
||||||
<literal>String</literal> representation (via the
|
<title>Custom Voters</title>
|
||||||
<literal>getAuthority()</literal> method) exactly equal to one or more
|
<para>It is also possible to implement a custom
|
||||||
<literal>ConfigAttributes</literal> starting with
|
<interfacename>AccessDecisionVoter</interfacename>. Several examples are provided in
|
||||||
<literal>ROLE_</literal>. If there is no exact match of any
|
Spring Security unit tests, including <literal>ContactSecurityVoter</literal> and
|
||||||
<literal>ConfigAttribute</literal> starting with
|
<literal>DenyVoter</literal>. The <literal>ContactSecurityVoter</literal> abstains
|
||||||
<literal>ROLE_</literal>, the <literal>RoleVoter</literal> will vote
|
from voting decisions where a <literal>CONTACT_OWNED_BY_CURRENT_USER</literal>
|
||||||
to deny access. If no <literal>ConfigAttribute</literal> begins with
|
<literal>ConfigAttribute</literal> is not found. If voting, it queries the
|
||||||
<literal>ROLE_</literal>, the voter will abstain.
|
<classname>MethodInvocation</classname> to extract the owner of the
|
||||||
<literal>RoleVoter</literal> is case sensitive on comparisons as well
|
<literal>Contact</literal> object that is subject of the method call. It votes to
|
||||||
as the <literal>ROLE_</literal> prefix.</para>
|
grant access if the <literal>Contact</literal> owner matches the principal presented in
|
||||||
</section>
|
the <interfacename>Authentication</interfacename> object. It could have just as easily
|
||||||
|
compared the <literal>Contact</literal> owner with some
|
||||||
<section>
|
<interfacename>GrantedAuthority</interfacename> the
|
||||||
<title>Custom Voters</title>
|
<interfacename>Authentication</interfacename> object presented. All of this is
|
||||||
<para>It is also possible to implement a custom
|
achieved with relatively few lines of code and demonstrates the flexibility of the
|
||||||
<interfacename>AccessDecisionVoter</interfacename>. Several examples are provided
|
authorization model.</para>
|
||||||
in Spring Security unit tests, including
|
|
||||||
<literal>ContactSecurityVoter</literal> and
|
|
||||||
<literal>DenyVoter</literal>. The
|
|
||||||
<literal>ContactSecurityVoter</literal> abstains from voting decisions
|
|
||||||
where a <literal>CONTACT_OWNED_BY_CURRENT_USER</literal>
|
|
||||||
<literal>ConfigAttribute</literal> is not found. If voting, it queries
|
|
||||||
the <classname>MethodInvocation</classname> 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
|
|
||||||
<interfacename>Authentication</interfacename> object. It could have just as easily
|
|
||||||
compared the <literal>Contact</literal> owner with some
|
|
||||||
<interfacename>GrantedAuthority</interfacename> the
|
|
||||||
<interfacename>Authentication</interfacename> object presented. All of this is
|
|
||||||
achieved with relatively few lines of code and demonstrates the
|
|
||||||
flexibility of the authorization model.</para>
|
|
||||||
</section>
|
</section>
|
||||||
</section>
|
|
||||||
</section>
|
</section>
|
||||||
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="after-invocation">
|
<section xml:id="after-invocation">
|
||||||
<info><title>After Invocation Handling</title></info>
|
<info>
|
||||||
<para>Whilst the <interfacename>AccessDecisionManager</interfacename> is called by
|
<title>After Invocation Handling</title>
|
||||||
the <classname>AbstractSecurityInterceptor</classname> before proceeding
|
</info>
|
||||||
with the secure object invocation, some applications need a way of
|
<para>Whilst the <interfacename>AccessDecisionManager</interfacename> is called by the
|
||||||
modifying the object actually returned by the secure object
|
<classname>AbstractSecurityInterceptor</classname> before proceeding with the secure object
|
||||||
invocation. Whilst you could easily implement your own AOP concern to
|
invocation, some applications need a way of modifying the object actually returned by the
|
||||||
achieve this, Spring Security provides a convenient hook that has
|
secure object invocation. Whilst you could easily implement your own AOP concern to achieve
|
||||||
several concrete implementations that integrate with its ACL
|
this, Spring Security provides a convenient hook that has several concrete implementations
|
||||||
capabilities.</para>
|
that integrate with its ACL capabilities.</para>
|
||||||
|
|
||||||
<para><xref linkend="authz-after-invocation"/> illustrates Spring Security's
|
<para><xref linkend="authz-after-invocation"/> illustrates Spring Security's
|
||||||
<literal>AfterInvocationManager</literal> and its concrete
|
<literal>AfterInvocationManager</literal> and its concrete implementations. <figure
|
||||||
implementations.
|
xml:id="authz-after-invocation">
|
||||||
|
<title>After Invocation Implementation</title>
|
||||||
<figure xml:id="authz-after-invocation">
|
<mediaobject>
|
||||||
<title>After Invocation Implementation</title>
|
<imageobject>
|
||||||
<mediaobject>
|
<imagedata align="center" scalefit="1" fileref="images/AfterInvocation.gif" format="GIF"
|
||||||
<imageobject>
|
/>
|
||||||
<imagedata align="center" scalefit="1" fileref="images/AfterInvocation.gif" format="GIF"/>
|
</imageobject>
|
||||||
</imageobject>
|
</mediaobject>
|
||||||
</mediaobject>
|
</figure></para>
|
||||||
|
<para>Like many other parts of Spring Security, <literal>AfterInvocationManager</literal> has a
|
||||||
</figure>
|
single concrete implementation, <literal>AfterInvocationProviderManager</literal>, which polls
|
||||||
</para>
|
a list of <literal>AfterInvocationProvider</literal>s. Each
|
||||||
|
<literal>AfterInvocationProvider</literal> is allowed to modify the return object or throw
|
||||||
<para>Like many other parts of Spring Security,
|
an <literal>AccessDeniedException</literal>. Indeed multiple providers can modify the object,
|
||||||
<literal>AfterInvocationManager</literal> has a single concrete
|
as the result of the previous provider is passed to the next in the list. Let's now consider
|
||||||
implementation, <literal>AfterInvocationProviderManager</literal>,
|
our ACL-aware implementations of <literal>AfterInvocationProvider</literal>.</para>
|
||||||
which polls a list of <literal>AfterInvocationProvider</literal>s.
|
<para>Please be aware that if you're using <literal>AfterInvocationManager</literal>, you will
|
||||||
Each <literal>AfterInvocationProvider</literal> is allowed to modify
|
still need configuration attributes that allow the
|
||||||
the return object or throw an
|
<classname>MethodSecurityInterceptor</classname>'s
|
||||||
<literal>AccessDeniedException</literal>. Indeed multiple providers
|
<interfacename>AccessDecisionManager</interfacename> to allow an operation. If you're using
|
||||||
can modify the object, as the result of the previous provider is
|
the typical Spring Security included <interfacename>AccessDecisionManager</interfacename>
|
||||||
passed to the next in the list. Let's now consider our ACL-aware
|
implementations, having no configuration attributes defined for a particular secure method
|
||||||
implementations of <literal>AfterInvocationProvider</literal>.</para>
|
invocation will cause each <interfacename>AccessDecisionVoter</interfacename> to abstain from
|
||||||
|
voting. In turn, if the <interfacename>AccessDecisionManager</interfacename> property
|
||||||
<para>Please be aware that if you're using
|
"<literal>allowIfAllAbstainDecisions</literal>" is <literal>false</literal>, an
|
||||||
<literal>AfterInvocationManager</literal>, you will still need
|
<literal>AccessDeniedException</literal> will be thrown. You may avoid this potential issue
|
||||||
configuration attributes that allow the
|
by either (i) setting "<literal>allowIfAllAbstainDecisions</literal>" to
|
||||||
<classname>MethodSecurityInterceptor</classname>'s
|
<literal>true</literal> (although this is generally not recommended) or (ii) simply ensure
|
||||||
<interfacename>AccessDecisionManager</interfacename> to allow an operation. If
|
that there is at least one configuration attribute that an
|
||||||
you're using the typical Spring Security included
|
<interfacename>AccessDecisionVoter</interfacename> will vote to grant access for. This
|
||||||
<interfacename>AccessDecisionManager</interfacename> implementations, having no
|
latter (recommended) approach is usually achieved through a <literal>ROLE_USER</literal> or
|
||||||
configuration attributes defined for a particular secure method
|
<literal>ROLE_AUTHENTICATED</literal> configuration attribute</para>
|
||||||
invocation will cause each <interfacename>AccessDecisionVoter</interfacename> to
|
<section xml:id="after-invocation-acl-aware">
|
||||||
abstain from voting. In turn, if the
|
<info>
|
||||||
<interfacename>AccessDecisionManager</interfacename> property
|
<title>ACL-Aware AfterInvocationProviders</title>
|
||||||
"<literal>allowIfAllAbstainDecisions</literal>" is
|
</info>
|
||||||
<literal>false</literal>, an <literal>AccessDeniedException</literal>
|
<!-- TODO: Move to ACL section and add reference here -->
|
||||||
will be thrown. You may avoid this potential issue by either (i)
|
<para>A common services layer method we've all written at one stage or another looks like
|
||||||
setting "<literal>allowIfAllAbstainDecisions</literal>" to
|
this:</para>
|
||||||
<literal>true</literal> (although this is generally not recommended)
|
<para>
|
||||||
or (ii) simply ensure that there is at least one configuration
|
<programlisting>public Contact getById(Integer id);</programlisting>
|
||||||
attribute that an <interfacename>AccessDecisionVoter</interfacename> will vote to
|
</para>
|
||||||
grant access for. This latter (recommended) approach is usually
|
<para>Quite often, only principals with permission to read the <literal>Contact</literal>
|
||||||
achieved through a <literal>ROLE_USER</literal> or
|
should be allowed to obtain it. In this situation the
|
||||||
<literal>ROLE_AUTHENTICATED</literal> configuration attribute</para>
|
<interfacename>AccessDecisionManager</interfacename> approach provided by the
|
||||||
|
<classname>AbstractSecurityInterceptor</classname> will not suffice. This is because the
|
||||||
<section xml:id="after-invocation-acl-aware"><info><title>ACL-Aware AfterInvocationProviders</title></info>
|
identity of the <literal>Contact</literal> is all that is available before the secure object
|
||||||
<!-- TODO: Move to ACL section and add reference here -->
|
is invoked. The <classname>AclEntryAfterInvocationProvider</classname> delivers a solution,
|
||||||
<para>A common services layer method we've all written at one stage
|
and is configured as follows: <programlisting><![CDATA[
|
||||||
or another looks like this:</para>
|
|
||||||
|
|
||||||
<para><programlisting>public Contact getById(Integer id);</programlisting></para>
|
|
||||||
|
|
||||||
<para>Quite often, only principals with permission to read the
|
|
||||||
<literal>Contact</literal> should be allowed to obtain it. In this
|
|
||||||
situation the <interfacename>AccessDecisionManager</interfacename> approach
|
|
||||||
provided by the <classname>AbstractSecurityInterceptor</classname> will
|
|
||||||
not suffice. This is because the identity of the
|
|
||||||
<literal>Contact</literal> is all that is available before the
|
|
||||||
secure object is invoked. The
|
|
||||||
<classname>AclEntryAfterInvocationProvider</classname> delivers a solution,
|
|
||||||
and is configured as follows:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<bean id="afterAclRead"
|
<bean id="afterAclRead"
|
||||||
class="org.springframework.security.acls.afterinvocation.AclEntryAfterInvocationProvider">
|
class="org.springframework.security.acls.afterinvocation.AclEntryAfterInvocationProvider">
|
||||||
<constructor-arg ref="aclService"/>
|
<constructor-arg ref="aclService"/>
|
||||||
|
@ -298,26 +249,19 @@ boolean supports(Class clazz);
|
||||||
</list>
|
</list>
|
||||||
</constructor-arg>
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
]]></programlisting>
|
]]></programlisting> In the above example, the <literal>Contact</literal> will be retrieved and
|
||||||
In the above example, the <literal>Contact</literal> will be
|
passed to the <classname>AclEntryAfterInvocationProvider</classname>. The provider will
|
||||||
retrieved and passed to the
|
thrown an <classname>AccessDeniedException</classname> if one of the listed
|
||||||
<classname>AclEntryAfterInvocationProvider</classname>. The provider
|
<literal>requirePermission</literal>s is not held by the
|
||||||
will thrown an <classname>AccessDeniedException</classname> if one of
|
<interfacename>Authentication</interfacename>. The
|
||||||
the listed <literal>requirePermission</literal>s is not held by the
|
<classname>AclEntryAfterInvocationProvider</classname> queries the acl service to
|
||||||
<interfacename>Authentication</interfacename>. The
|
determine the ACL that applies for this domain object to this
|
||||||
<classname>AclEntryAfterInvocationProvider</classname> queries the
|
<interfacename>Authentication</interfacename>.</para>
|
||||||
acl service to determine the ACL that applies for
|
<para>Similar to the <classname>AclEntryAfterInvocationProvider</classname> is
|
||||||
this domain object to this <interfacename>Authentication</interfacename>.</para>
|
<classname>AclEntryAfterInvocationCollectionFilteringProvider</classname>. It is designed
|
||||||
|
to remove <literal>Collection</literal> or array elements for which a principal does not
|
||||||
<para>Similar to the
|
have access. It never thrown an <classname>AccessDeniedException</classname> - simply
|
||||||
<classname>AclEntryAfterInvocationProvider</classname> is
|
silently removes the offending elements. The provider is configured as follows: <programlisting><![CDATA[
|
||||||
<classname>AclEntryAfterInvocationCollectionFilteringProvider</classname>.
|
|
||||||
It is designed to remove <literal>Collection</literal> or array
|
|
||||||
elements for which a principal does not have access. It never thrown
|
|
||||||
an <classname>AccessDeniedException</classname> - simply silently
|
|
||||||
removes the offending elements. The provider is configured as
|
|
||||||
follows:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<bean id="afterAclCollectionRead"
|
<bean id="afterAclCollectionRead"
|
||||||
class="org.springframework.security.acls.afterinvocation.AclEntryAfterInvocationCollectionFilteringProvider">
|
class="org.springframework.security.acls.afterinvocation.AclEntryAfterInvocationCollectionFilteringProvider">
|
||||||
<constructor-arg ref="aclService"/>
|
<constructor-arg ref="aclService"/>
|
||||||
|
@ -328,109 +272,83 @@ boolean supports(Class clazz);
|
||||||
</list>
|
</list>
|
||||||
</constructor-arg>
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
]]> </programlisting>
|
]]> </programlisting> As you can imagine, the returned <literal>Object</literal> must be a
|
||||||
As you can imagine, the returned <literal>Object</literal>
|
<literal>Collection</literal> or array for this provider to operate. It will remove any
|
||||||
must be a <literal>Collection</literal> or array for this provider
|
element if the <literal>AclManager</literal> indicates the
|
||||||
to operate. It will remove any element if the
|
<interfacename>Authentication</interfacename> does not hold one of the listed
|
||||||
<literal>AclManager</literal> indicates the
|
<literal>requirePermission</literal>s.</para>
|
||||||
<interfacename>Authentication</interfacename> does not hold one of the listed
|
|
||||||
<literal>requirePermission</literal>s.</para>
|
|
||||||
|
|
||||||
<para>The Contacts sample application demonstrates these two
|
<para>The Contacts sample application demonstrates these two
|
||||||
<literal>AfterInvocationProvider</literal>s.</para>
|
<literal>AfterInvocationProvider</literal>s.</para>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="authorization-taglibs">
|
<section xml:id="authorization-taglibs">
|
||||||
<info><title>Authorization Tag Libraries</title></info>
|
<info>
|
||||||
|
<title>Authorization Tag Libraries</title>
|
||||||
<para><literal>AuthorizeTag</literal> is used to include content if
|
</info>
|
||||||
the current principal holds certain
|
<para><literal>AuthorizeTag</literal> is used to include content if the current principal holds
|
||||||
<interfacename>GrantedAuthority</interfacename>s.</para>
|
certain <interfacename>GrantedAuthority</interfacename>s.</para>
|
||||||
|
|
||||||
<para>The following JSP fragment illustrates how to use the
|
<para>The following JSP fragment illustrates how to use the
|
||||||
<literal>AuthorizeTag</literal>:</para>
|
<literal>AuthorizeTag</literal>:</para>
|
||||||
|
<para>
|
||||||
<para><programlisting>
|
<programlisting>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
<security:authorize ifAllGranted="ROLE_SUPERVISOR">
|
<security:authorize ifAllGranted="ROLE_SUPERVISOR">
|
||||||
<td>
|
<td>
|
||||||
<a href="del.htm?id=<c:out value="${contact.id}"/>">Del</a>
|
<a href="del.htm?id=<c:out value="${contact.id}"/>">Del</a>
|
||||||
</td>
|
</td>
|
||||||
</security:authorize>
|
</security:authorize>
|
||||||
]]></programlisting></para>
|
]]></programlisting>
|
||||||
|
</para>
|
||||||
<para>This tag would cause the tag's body to be output if the
|
<para>This tag would cause the tag's body to be output if the principal has been granted
|
||||||
principal has been granted ROLE_SUPERVISOR.</para>
|
ROLE_SUPERVISOR.</para>
|
||||||
|
<para>The <literal>security:authorize</literal> tag declares the following attributes:</para>
|
||||||
<para>The <literal>security:authorize</literal> tag declares the
|
<para>
|
||||||
following attributes:</para>
|
<itemizedlist spacing="compact">
|
||||||
|
|
||||||
<para><itemizedlist spacing="compact">
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para><literal>ifAllGranted</literal>: All the listed roles must
|
<para><literal>ifAllGranted</literal>: All the listed roles must be granted for the tag to
|
||||||
be granted for the tag to output its body.</para>
|
output its body.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para><literal>ifAnyGranted</literal>: Any of the listed roles
|
<para><literal>ifAnyGranted</literal>: Any of the listed roles must be granted for the tag
|
||||||
must be granted for the tag to output its body.</para>
|
to output its body.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para><literal>ifNotGranted</literal>: None of the listed roles
|
<para><literal>ifNotGranted</literal>: None of the listed roles must be granted for the
|
||||||
must be granted for the tag to output its body.</para>
|
tag to output its body.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist></para>
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
<para>You'll note that in each attribute you can list multiple roles.
|
<para>You'll note that in each attribute you can list multiple roles. Simply separate the roles
|
||||||
Simply separate the roles using a comma. The
|
using a comma. The <literal>authorize</literal> tag ignores whitespace in attributes.</para>
|
||||||
<literal>authorize</literal> tag ignores whitespace in
|
<para>The tag library logically ANDs all of it's parameters together. This means that if you
|
||||||
attributes.</para>
|
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
|
||||||
<para>The tag library logically ANDs all of it's parameters together.
|
<literal>ifNotGranted="ROLE_SUPERVISOR"</literal>, or you'll be surprised to never see the
|
||||||
This means that if you combine two or more attributes, all attributes
|
tag's body.</para>
|
||||||
must be true for the tag to output it's body. Don't add an
|
<para>By requiring all attributes to return true, the authorize tag allows you to create more
|
||||||
<literal>ifAllGranted="ROLE_SUPERVISOR"</literal>, followed by an
|
complex authorization scenarios. For example, you could declare an
|
||||||
<literal>ifNotGranted="ROLE_SUPERVISOR"</literal>, or you'll be
|
<literal>ifAllGranted="ROLE_SUPERVISOR"</literal> and an
|
||||||
surprised to never see the tag's body.</para>
|
<literal>ifNotGranted="ROLE_NEWBIE_SUPERVISOR"</literal> in the same tag, in order to
|
||||||
|
prevent new supervisors from seeing the tag body. However it would no doubt be simpler to use
|
||||||
<para>By requiring all attributes to return true, the authorize tag
|
<literal>ifAllGranted="ROLE_EXPERIENCED_SUPERVISOR"</literal> rather than inserting NOT
|
||||||
allows you to create more complex authorization scenarios. For
|
conditions into your design.</para>
|
||||||
example, you could declare an
|
<para>One last item: the tag verifies the authorizations in a specific order: first
|
||||||
<literal>ifAllGranted="ROLE_SUPERVISOR"</literal> and an
|
<literal>ifNotGranted</literal>, then <literal>ifAllGranted</literal>, and finally,
|
||||||
<literal>ifNotGranted="ROLE_NEWBIE_SUPERVISOR"</literal> in the same
|
<literal>if AnyGranted</literal>.</para>
|
||||||
tag, in order to prevent new supervisors from seeing the tag body.
|
<para><literal>AccessControlListTag</literal> is used to include content if the current
|
||||||
However it would no doubt be simpler to use
|
principal has an ACL to the indicated domain object.</para>
|
||||||
<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>if
|
|
||||||
AnyGranted</literal>.</para>
|
|
||||||
|
|
||||||
<para><literal>AccessControlListTag</literal> is used to include
|
|
||||||
content if the current principal has an ACL to the indicated domain
|
|
||||||
object.</para>
|
|
||||||
|
|
||||||
<para>The following JSP fragment illustrates how to use the
|
<para>The following JSP fragment illustrates how to use the
|
||||||
<literal>AccessControlListTag</literal>:
|
<literal>AccessControlListTag</literal>: <programlisting><![CDATA[
|
||||||
<programlisting><![CDATA[
|
|
||||||
<security:accesscontrollist domainObject="${contact}" hasPermission="8,16">
|
<security:accesscontrollist domainObject="${contact}" hasPermission="8,16">
|
||||||
<td><a href="<c:url value="del.htm"><c:param name="contactId" value="${contact.id}"/></c:url>">Del</a></td>
|
<td><a href="<c:url value="del.htm"><c:param name="contactId" value="${contact.id}"/></c:url>">Del</a></td>
|
||||||
</security:accesscontrollist>
|
</security:accesscontrollist>
|
||||||
]]></programlisting>
|
]]></programlisting> This tag would cause the tag's body to be output if the principal holds either
|
||||||
This tag would cause the tag's body to be output if the
|
permission 16 or permission 1 for the "contact" domain object. The numbers are actually
|
||||||
principal holds either permission 16 or permission 1 for the "contact"
|
integers that are used with <literal>BasePermission</literal> bit masking. Please refer to the
|
||||||
domain object. The numbers are actually integers that are used with
|
ACL section of this reference guide to understand more about the ACL capabilities of Spring
|
||||||
<literal>BasePermission</literal> bit masking. Please refer to the ACL
|
Security.</para>
|
||||||
section of this reference guide to understand more about the ACL
|
<para><literal>AclTag</literal> is part of the old ACL module and should be considered
|
||||||
capabilities of Spring Security.</para>
|
deprecated. For the sake of historical reference, works exactly the samae as
|
||||||
|
<literal>AccessControlListTag</literal>.</para>
|
||||||
<para><literal>AclTag</literal> is part of the old ACL module and
|
|
||||||
should be considered deprecated. For the sake of historical reference,
|
|
||||||
works exactly the samae as
|
|
||||||
<literal>AccessControlListTag</literal>.</para>
|
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -637,20 +637,6 @@
|
||||||
in the list of pointcuts, as the first matching expression will be used. </para>
|
in the list of pointcuts, as the first matching expression will be used. </para>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="ns-intercept-methods">
|
|
||||||
<title>The <literal>intercept-methods</literal> Bean Decorator</title>
|
|
||||||
<para> This alternative syntax allows you to specify security for a specific bean by adding
|
|
||||||
this element within the bean itself. <programlisting language="xml"><![CDATA[
|
|
||||||
<bean:bean id="target" class="com.mycompany.myapp.MyBean">
|
|
||||||
<intercept-methods>
|
|
||||||
<protect method="set*" access="ROLE_ADMIN" />
|
|
||||||
<protect method="get*" access="ROLE_ADMIN,ROLE_USER" />
|
|
||||||
<protect method="doSomething" access="ROLE_USER" />
|
|
||||||
</intercept-methods>
|
|
||||||
</bean:bean>
|
|
||||||
]]></programlisting> This allows you to configure security attributes for individual methods on the
|
|
||||||
bean or simple wildcarded patterns. </para>
|
|
||||||
</section>
|
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="ns-access-manager">
|
<section xml:id="ns-access-manager">
|
||||||
<title>The Default AccessDecisionManager</title>
|
<title>The Default AccessDecisionManager</title>
|
||||||
|
|
|
@ -76,7 +76,7 @@ if (principal instanceof UserDetails) {
|
||||||
}</programlisting>
|
}</programlisting>
|
||||||
<para>The object returned by the call to <methodname>getContext()</methodname> is an
|
<para>The object returned by the call to <methodname>getContext()</methodname> is an
|
||||||
instance of the <interfacename>SecurityContext</interfacename> interface. This is the
|
instance of the <interfacename>SecurityContext</interfacename> interface. This is the
|
||||||
object that is kept in thread-local storage. As we'll see below, Most authentication
|
object that is kept in thread-local storage. As we'll see below, Most authentication
|
||||||
mechanisms withing Spring Security return an instance of
|
mechanisms withing Spring Security return an instance of
|
||||||
<interfacename>UserDetails</interfacename> as the principal. </para>
|
<interfacename>UserDetails</interfacename> as the principal. </para>
|
||||||
</section>
|
</section>
|
||||||
|
@ -127,7 +127,7 @@ if (principal instanceof UserDetails) {
|
||||||
<interfacename>Authentication</interfacename> is <literal>getAuthorities(</literal>). This
|
<interfacename>Authentication</interfacename> is <literal>getAuthorities(</literal>). This
|
||||||
method provides an array of <interfacename>GrantedAuthority</interfacename> objects. A
|
method provides an array of <interfacename>GrantedAuthority</interfacename> objects. A
|
||||||
<interfacename>GrantedAuthority</interfacename> is, not surprisingly, an authority that is
|
<interfacename>GrantedAuthority</interfacename> is, not surprisingly, an authority that is
|
||||||
granted to the principal. Such authorities are usually "roles", such as
|
granted to the principal. Such authorities are usually <quote>roles</quote>, such as
|
||||||
<literal>ROLE_ADMINISTRATOR</literal> or <literal>ROLE_HR_SUPERVISOR</literal>. These
|
<literal>ROLE_ADMINISTRATOR</literal> or <literal>ROLE_HR_SUPERVISOR</literal>. These
|
||||||
roles are later on configured for web authorization, method authorization and domain object
|
roles are later on configured for web authorization, method authorization and domain object
|
||||||
authorization. Other parts of Spring Security are capable of interpreting these authorities,
|
authorization. Other parts of Spring Security are capable of interpreting these authorities,
|
||||||
|
|
Loading…
Reference in New Issue