mirror of
https://github.com/spring-projects/spring-security.git
synced 2026-02-01 19:19:40 +00:00
181 lines
9.7 KiB
XML
181 lines
9.7 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
|
|
"http://www.docbook.org/xml/4.4/docbookx.dtd">
|
|
|
|
<chapter id="domain-acls">
|
|
|
|
<title>Domain Object Security</title>
|
|
|
|
<section id="domain-acls-overview">
|
|
<title>Overview</title>
|
|
|
|
<para>PLEASE NOTE: Acegi Security 1.0.3 contains a preview of a new
|
|
ACL module. The new ACL module is a significant rewrite of the
|
|
existing ACL module. The new module can be found under the
|
|
<literal>org.springframework.security.acls</literal> package, with the
|
|
old ACL module under
|
|
<literal>org.springframework.security.acl</literal>. We encourage
|
|
users to consider testing with the new ACL module and build
|
|
applications with it. The old ACL module should be considered
|
|
deprecated and may be removed from a future release.</para>
|
|
|
|
<para>Complex applications often will find the need to define access
|
|
permissions not simply at a web request or method invocation level.
|
|
Instead, security decisions need to comprise both who
|
|
(<literal>Authentication</literal>), where
|
|
(<literal>MethodInvocation</literal>) and what
|
|
(<literal>SomeDomainObject</literal>). In other words, authorization
|
|
decisions also need to consider the actual domain object instance
|
|
subject of a method invocation.</para>
|
|
|
|
<para>Imagine you're designing an application for a pet clinic. There
|
|
will be two main groups of users of your Spring-based application:
|
|
staff of the pet clinic, as well as the pet clinic's customers. The
|
|
staff will have access to all of the data, whilst your customers will
|
|
only be able to see their own customer records. To make it a little
|
|
more interesting, your customers can allow other users to see their
|
|
customer records, such as their "puppy preschool "mentor or president
|
|
of their local "Pony Club". Using Spring Security as the foundation,
|
|
you have several approaches that can be used:<orderedlist>
|
|
<listitem>
|
|
<para>Write your business methods to enforce the security. You
|
|
could consult a collection within the
|
|
<literal>Customer</literal> domain object instance to determine
|
|
which users have access. By using the
|
|
<literal>SecurityContextHolder.getContext().getAuthentication()</literal>,
|
|
you'll be able to access the <literal>Authentication</literal>
|
|
object.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Write an <literal>AccessDecisionVoter</literal> to enforce
|
|
the security from the <literal>GrantedAuthority[]</literal>s
|
|
stored in the <literal>Authentication</literal> object. This
|
|
would mean your <literal>AuthenticationManager</literal> would
|
|
need to populate the <literal>Authentication</literal> with
|
|
custom <literal>GrantedAuthority</literal>[]s representing each
|
|
of the <literal>Customer</literal> domain object instances the
|
|
principal has access to.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Write an <literal>AccessDecisionVoter</literal> to enforce
|
|
the security and open the target <literal>Customer</literal>
|
|
domain object directly. This would mean your voter needs access
|
|
to a DAO that allows it to retrieve the
|
|
<literal>Customer</literal> object. It would then access the
|
|
<literal>Customer</literal> object's collection of approved
|
|
users and make the appropriate decision.</para>
|
|
</listitem>
|
|
</orderedlist></para>
|
|
|
|
<para>Each one of these approaches is perfectly legitimate. However,
|
|
the first couples your authorization checking to your business code.
|
|
The main problems with this include the enhanced difficulty of unit
|
|
testing and the fact it would be more difficult to reuse the
|
|
<literal>Customer</literal> authorization logic elsewhere. Obtaining
|
|
the <literal>GrantedAuthority[]</literal>s from the
|
|
<literal>Authentication</literal> object is also fine, but will not
|
|
scale to large numbers of <literal>Customer</literal>s. If a user
|
|
might be able to access 5,000 <literal>Customer</literal>s (unlikely
|
|
in this case, but imagine if it were a popular vet for a large Pony
|
|
Club!) the amount of memory consumed and time required to construct
|
|
the <literal>Authentication</literal> object would be undesirable. The
|
|
final method, opening the <literal>Customer</literal> directly from
|
|
external code, is probably the best of the three. It achieves
|
|
separation of concerns, and doesn't misuse memory or CPU cycles, but
|
|
it is still inefficient in that both the
|
|
<literal>AccessDecisionVoter</literal> and the eventual business
|
|
method itself will perform a call to the DAO responsible for
|
|
retrieving the <literal>Customer</literal> object. Two accesses per
|
|
method invocation is clearly undesirable. In addition, with every
|
|
approach listed you'll need to write your own access control list
|
|
(ACL) persistence and business logic from scratch.</para>
|
|
|
|
<para>Fortunately, there is another alternative, which we'll talk
|
|
about below.</para>
|
|
</section>
|
|
|
|
<section id="domain-acls-key-concepts">
|
|
<title>Key Concepts</title>
|
|
|
|
<para>The org.springframework.security.acls package should be
|
|
consulted for its major interfaces. The key interfaces are:</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><literal>Acl</literal>: Every domain object has one and only
|
|
one <literal>Acl</literal> object, which internally holds the
|
|
<literal>AccessControlEntry</literal>s as well as knows the owner
|
|
of the <literal>Acl</literal>. An Acl does not refer directly to
|
|
the domain object, but instead to an
|
|
<literal>ObjectIdentity</literal>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal><literal>AccessControlEntry</literal></literal>: An
|
|
Acl holds multiple <literal>AccessControlEntry</literal>s, which
|
|
are often abbreviated as ACEs in the framework. Each ACE refers to
|
|
a specific tuple of <literal>Permission</literal>,
|
|
<literal>Sid</literal> and <literal>Acl</literal>. An ACE can also
|
|
be granting or non-granting and contain audit settings.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Permission</literal>: A permission represents an
|
|
immutable particular bit mask, and offers convenience functions
|
|
for bit masking and outputting information.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>Sid</literal>: The ACL module needs to refer to
|
|
principals and <literal>GrantedAuthority[]</literal>s. A level of
|
|
indirection is provided by the <literal>Sid</literal> interface.
|
|
Common classes include <literal>PrincipalSid</literal> (to
|
|
represent the principal inside an
|
|
<literal>Authentication</literal> object) and
|
|
<literal>GrantedAuthoritySid</literal>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>ObjectIdentity</literal>: Each domain object is
|
|
represented internally within the ACL module by an
|
|
<literal>ObjectIdentity</literal>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>AclService</literal>: Retrieves the
|
|
<literal>Acl</literal> applicable for a given
|
|
<literal>ObjectIdentity</literal>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>MutableAclService</literal>: Allows a modified
|
|
<literal>Acl</literal> to be presented for persistence. It is not
|
|
essential to use this interface if you do not wish.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>The ACL module was based on extensive feedback from the user
|
|
community following real-world use of the original ACL module. This
|
|
feedback resulted in a rearchitecture of the ACL module to offer
|
|
significantly enhanced performance (particularly in the area of
|
|
database retrieval), significantly better encapsulation, higher
|
|
cohesion, and enhanced customisation points.</para>
|
|
|
|
<para>The Contacts Sample that ships with Acegi Security 1.0.3 offers
|
|
a demonstration of the new ACL module. Converting Contacts from using
|
|
the old module to the new module was relatively simple, and users of
|
|
the old ACL module will likely find their applications can be modified
|
|
with relatively little work.</para>
|
|
|
|
<para>We will document the new ACL module more fully with a subsequent
|
|
release. Please note that the new ACL module should be considered a
|
|
preview only (ie do not use in production without proper prior
|
|
testing), and there is a small chance there may be changes between
|
|
1.0.3 and 1.1.0 when it will become final. Nevertheless,
|
|
compatibility-affecting changes are considered quite unlikely,
|
|
especially given the module is already based on several years of
|
|
feedback from users of the original ACL module.</para>
|
|
</section>
|
|
</chapter> |