Notes on Spring Security

pyknicassortedSecurity

Nov 3, 2013 (3 years and 5 months ago)

80 views

Page
1

of
16

Notes on
Spring

Security

Created 03/06/11

Updated 04/13/11
,
Updated 05/15
/11
, Updated 05/28/11
, Updated 08/16/11, Updated 09/17/11
, Updated 09/24/11

Updated 09/28/11
, Updated 11/23/11
, Updated 11/27
/11
, Updated 12/23
/11


Introduction

................................
................................
................................
................................
................................
..................

1

Resources

................................
................................
................................
................................
................................
.................

1

Concepts
................................
................................
................................
................................
................................
........................

2

Com
ponents of the Framework

................................
................................
................................
................................
.................

2

Setting up Configuration

................................
................................
................................
................................
.......................

3

Securing Web Requests

................................
................................
................................
................................
..............................

4

Using Authorization Annotations

................................
................................
................................
................................
........

5

Securing Screens
................................
................................
................................
................................
................................
..........

6

The Tags

................................
................................
................................
................................
................................
...................

6

The Default AccessDecisionManager

................................
................................
................................
................................
.

6

Expression Based Access Control
................................
................................
................................
................................
........

6

Managing Authentication
................................
................................
................................
................................
...........................

7

Reading from LDAP

................................
................................
................................
................................
..............................

7

Securing Method Calls

................................
................................
................................
................................
...............................

8

@Pre

and
@Post

Annotations

................................
................................
................................
................................
............

8

Access Control using
@PreAuthorize

and
@PostAuthorize

................................
................................
............

8

Using Declarative Specifications

................................
................................
................................
................................
.........

9

Built
-
In Expressions

................................
................................
................................
................................
...............................

9

Forwarding to an error screen
................................
................................
................................
................................
.............

10

Using Access Control Lists
................................
................................
................................
................................
......................

10

Using Spring Security in Grails

................................
................................
................................
................................
..............

12

Installation
................................
................................
................................
................................
................................
..............

12

Basic Configuration
................................
................................
................................
................................
..............................

12

Hierarchical Roles

................................
................................
................................
................................
................................

13

Advanced Configuration
................................
................................
................................
................................
......................

14

Custom Authentication Decision

................................
................................
................................
................................
.......

14

Open Questions/Issues
................................
................................
................................
................................
..............................

16

Appendix A: Example Programs that are based on Spring Security

................................
................................
...............

16

Introduction

Spring Security is a powerful and highly customizable authentication and access
-
control framework.

It is the de
-
facto standard for securing Spring
-
based applicat
ions.


Spring Security is one of the most mature and widely used Spring projects.


Founded in 2003 and actively
maintained by SpringSource since, today it is used to secure numerous demanding environments including
government agencies, military applications and central banks.



Spring Security tackles security from two angles. To sec
ure web requests and restrict access at the
URL
level,
Spring Security uses servlet filters. Spring Security can also secure method invocations using Spring
AOP

proxying objects and applying advice that ensures that the user has proper authority to invoke

secured methods.


The c
urrent ve
rsion is 3.0.7 (released in 2011
)
, and it is 17
MB in size.

However, that depends upon Spring 3.0.6.
The newest version that uses Spring 3.0.5 is Spring Security 3.0.5 (released in 2010).


Within the Grails world, Spring S
ecurity is provided by a plugin called Spring Security Core.

Resources

The reference manual is a 134
-
page
PDF

located at

Page
2

of
16

http://static.springsource.
org/spring
-
security/site/docs/3.0.x/reference/springsecurity.pdf


“Spring in Action, Third Edition” by Craig Walls. Manning Press, June 2011, 424 pages. List price $49.99,
Amazon price $36.22, used from $33.22. Rated

3.5 stars on Amazon.com
.
Contains
a good chapter on Spring
Security.

Several of the examples here are from that chapter, in which an application called “Spitter” is being
developed.


“Spring Security 3” by
Peter Mularien
. Packt Pubishing, 2010. Rated 3 stars on Amazon.com.

Concepts

Spring Security provides standard API’s, hooks, and classes to handle the authentication and access control
requirements of your web a
pplication.


It intercedes by using servlet filters (which come before the Spring Dispatch Filter), and
AOP wrappers around
c
lasses and methods.


Plus, the framework provides for standard implementations of User and Role (called Authority) classes, so that you
don’t have to write them yourself.


Finally, the framework provides a large number of configuration options, a set of
shortcut configuration options, and
a set of tags that you can use in JSP’s, combined with the Spring Security API calls to use in your application.



Keep in mind that this is a “framework”


it makes almost no decisions about who can do what on its own,

instead
you provide callbacks to fetch valid users, callbacks to decision functions etc. However,
Spring Security

can save
you considerable time

and effort,

because you only need to write those callbacks and set the configuration options
and you are gett
ing the design effort of numerous developers applied to your application. Plus, since the framework
is a standard it is more likely that you will be able to find developers already familiar with it.


Finally,
the framework has sub
-
modules to read authenti
cation information from a variety of sources, including
LDAP and OpenID.

Components of the Framework

Here is a list of all compon
ents:


Page
3

of
16


Core
-

spring
-
security
-
core.jar

308KB

Contains core authentication and access
-
contol classes and interfaces, remoting support and basic provisioning APIs.
Required by any application which uses Spring Security. Supports standalone applications, re
mote clients, method
(service layer) security and JDBC user provisioning. Contains the top
-
level packages:



org.springframework.security.core



org.springframework.security.access



org.springframework.security.authentication



org.springframework.security.provis
ioning



org.springframework.security.remoting

Web
-

spring
-
security
-
web.jar

228KB

Contains filters and related web
-
security infrastructure code. Anything with a servlet API dependency. You'll need it
if you require Spring Security web authentication service
s and URL
-
based access
-
control. The main package is
org.springframework.security.web
.

Config
-

spring
-
security
-
config.jar

Contains the security namespace parsing code (and hence nothing that you are likely yo use directly in your
application). You need it
if you are using the Spring Security XML namespace for configuration. The main package
is
org.springframework.security.config
.


In Spring Security 3.0, the contents of the
spring
-
security
-
core

jar were stripped down to the bare
minimum. It no longer contai
ns any code related to web
-
application security, LDAP or namespace configuration.
We'll take a look here at some of the Java types that you'll find in the core module. They represent the building
blocks of the framework, so if you ever need to go beyond a
simple namespace configuration then it's important that
you understand what they are, even if you don't actually need to interact with them directly.

Setting up Configuration

The first thing you need to do is add the following filter declaration to your
we
b.xml
file:


<filter>

<filter
-
name>
springSecurityFilterChain
</filter
-
name>

<filter
-
class>
org.springframework.web.filter.DelegatingFilterProxy
</filter
-
class>

</filter>

<filter
-
mapping>

<filter
-
name>
springSecurityFilterChain
</filter
-
name>

<url
-
pattern>
/*
</ur
l
-
pattern>

</filter
-
mapping>


This provides a hook into the Spring Security web infrastructure.
DelegatingFilterProxy
is a Spring
Framework class which delegates to a filter implementation which is defined as a Spring bean in your application
context.

In

this case, the bean is named “springSecurityFilterChain”, which is an internal infrastructure bean created
by the namespace to handle web security. Note that you should not use this bean name yourself.

Once you've added
this to your
web.xml
, you're read
y to start editing your application context file.


Early versions of Spring Security required a seemingly endless amount of
XML
configuration to set up basic security
features. In contrast, using recent versions of Spring Security, the following snippet o
f
XML
packs a lot of punch:



<http auto
-
config="true">


<intercept
-
urlpattern="/**"

access="ROLE_SPITTER"/>

</http>


Page
4

of
16

We also get a few more freebies by setting the
auto
-
config
attribute to
true
.

Autoconfiguration gives our
application a free login pa
ge, support for
HTTP
Basic authentication, and support for logging out.

In fact, set
ting
auto
-
config
to
true
is equivalent to explicitly asking for those features like this:


<http>


<form
-
login/>


<http
-
basic/>


<logout/>


<intercept
-
urlpattern=
"/**"

access="ROLE_SPITTER"/>

</http>


There are also options to define the login screen, etc.


Even though we may not want to keep the user
-
generated login form, we can learn a lot from it.


For starters, we
know that Spring Security will process the log
in request at the path
/Spitter/j_spring_security_check
.
And it’s clear that the username and password should be submitted in the request as fields named
j_username
and
j_password
.

Armed with that information, we can create our own custom login page.


The

<logout>
element sets up a Spring Security filter that will invalidate a user ses
-

sion.

When used as is, the
filter set up by
<logout>
is mapped to /j_spring_security_ logout.

But so that this doesn’t collide with how we’ve
set up
DispatcherServlet
, we

need to override the filter’s
URL
much as we did for the login form.

To do that,
we need to set the
logout
-
url
attribute:
<logout logout
-
url="/static/j_spring_security_logout"/>
.

That
wraps up our discussion of what autoconfiguration gives us.


http://www.codercorp.com/blog/spring/security
-
spring/writing
-
custom
-
userdetailsservice
-
for
-
spring
-
security.html


Built around a set of B
eans, which are organized as:



Web/HTTP Security
-

the most complex part. Sets up the filters and related service beans used to apply the
framework authentication mechanisms, to secure URLs, render login and error pages and much more.



Business Object (Metho
d) Security
-

options for securing the service layer.



AuthenticationManager
-

handles authentication requests from other parts of the framework.



AccessDecisionManager
-

provides access decisions for web and method security. A default one will be
registered
, but you can also choose to use a custom one, declared using normal Spring bean syntax.



AuthenticationProvider
s
-

mechanisms against which the authentication manager authenticates users. The
namespace provides supports for several standard options and al
so a means of adding custom beans
declared using a traditional syntax.



UserDetailsService
-

closely related to authentication providers, but often also required by other beans.
There is typically only one such service.

Securing Web Requests

Everything you

do with a Java web application starts with an
HttpServletRequest
. And if the request is the
access point to a web application, then that’s where security for a web application should begin. The most basic
form of request
-
level security involves declaring
one or more
URL
patterns as requiring some level of granted
authority and preventing users without that authority from accessing the content behind those
URL
s. Taking it a step
further, you may want to require that certain
URL
s can only be accessed over
HT
TPS
.


Before you can restrict access to users with certain privileges, there must be a way to know who’s using the
application. Therefore, the application will need to authenticate the user, prompting them to log in and identify
themselves. Spring Securit
y supports these and many other forms of request
-
level security. To get started with web
security in Spring, we must set up the servlet filters that provide the various security features.


In the “Spring User’s Guide”, we saw how to use the Spring Expressi
on Language (SpEL) as an advanced technique
for wiring bean properties. As of version 3.0, Spring Security also supports SpEL as a means for declaring access
requirements. To enable it, we must set the
use
-
expressions
attribute of
<http>
to
true
:
<http aut
o
-
config="true"use
-
expressions="true"> ... </http>
Now we can start using SpEL expressions in the
access
Page
5

of
16

attribute. Here’s how to use a SpEL expression to require
ROLE_ADMIN
access for the
/admin/**
URL
pattern:
<intercept
-
urlpattern="/admin/**"access="has
Role('ROLE_ADMIN')"/>
This
<intercept
-
url>
is
effectively the same as the one we started with, except that it uses SpEL. The
hasRole()
expression evaluates to
true
if the current user has been granted the given authority. But
hasRole()
is only one of sever
al security
-
specific expressions supported. Table 9.2 lists all of the SpEL expressions added by Spring Security 3.0.


Submitting data across
HTTP
can be a risky proposition. It may not be a big deal to send a spittle message in the
clear over
HTTP
. But if

you’re passing sensitive infor
ma
tion such as passwords and credit card numbers across
HTTP
, then you’re asking for trouble. That’s why sensitive information should be sent encrypted over
HTTPS
.
Working with
HTTPS
seems simple enough. All you have to do is

add an
s
after the
http
in a
URL
and you’re set.
Right? That’s true, but it places responsibility for using the
HTTPS
channel in the wrong place. If you have dozens or
hundreds of links and form actions that should be going to an
HTTPS URL
, it’s too easy
to forget to add that S.
Chances are good that you’ll miss one or two of them. Or you may overcorrect and use
HTTPS
in places where it’s
unnecessary. The
<intercept
-
url>
element’s
requires
-
channel
attribute shifts the responsi
bility for
channel enforcement

into the Spring Security configuration. As an example, consider the Spitter application’s
re
gistration form. Although Spit
ter doesn’t ask for credit card numbers or social security numbers or anything
terribly sensitive, the users may want that informatio
n to be kept private. In that case, we should configure an
<intercept
-
url>
element for the /spitter/form like this:
<intercept
-
urlpattern="/spitter/form"requires
-
channel="https"/>


Anytime a request comes in for /spitter/form, Spring Security will see tha
t it requires the
https
channel and
automatically redirect the request to go over
HTTPS
.

Likewise, the home page doesn’t require
HTTPS
, so we can
declare that it always should be sent over
HTTP
:
<intercept
-
urlpattern="/home"requires
-
channel="http"/>


So
far we’ve seen how to secure web applications as

requests are made.

The assump
tion has been that security
would involve stopping a user from accessing a
URL
that they’re not authorized to use.

But it’s also a good idea to
never show links that a user won
’t be able to follow.

Let’s see how Spring Security offers security in the view.

Using Authorization Annotations

This is the job of the AccessDecisionManager and its related

object
s. Also availa
b
l
e globally.


From version 2.0 onwards Spring Security has
improved support substantia
lly for adding security to your
service
layer methods.

It provides support for JSR
-
250 annotation security as well as the framework's

original
@Secured
annotation.

From 3.0 you can also make use of new expression
-
based annotati
ons.


You can apply security to a single bean, using the
intercept
-
methods
element to decorate the
bean
declaration, or you can secure multiple beans across the entire service layer using the AspectJ

style pointcuts.


The
<global
-
method
-
security>
Element

T
his element is used to enable annotation
-
based security in your application (by setting the appropriate

attributes on
the element), and also to group together security pointcut declarations which will be applied

across your entire
application context.

You

should only declare one
<global
-
method
-
security>

element.

The following

declaration would enable support for Spring Security's
@Secured
:


<global
-
method
-
security secured
-
annotations="enabled" />


Adding an annotation to a method (on an class or interfac
e) would then limit the access to that method accordingly.
Spring Security's native annotation support defines a set of attributes for the method.

These will be passed to the
AccessDecisionManager

for it to make the actual decision.


To get the @Secured a
nnotation to apply to the Controllers, it must be in the spring
-
servlet.xml configuration file.

Page
6

of
16

Securing Screens

The Tags

There is a library of tags which must be added. Then add the following line to your JSP files:


<%@ taglib prefix=
"sec"

uri=
"http://w
ww.springframework.org/security/tags"

%>


Use the following tag:

<sec:authorize access=
"isAuthenticated()"
>

</sec:authorize>


To contain code that should only appear when a user is logged in.

The Default AccessDecisionManager

This section assumes you have
some knowledge of the underlying architecture for access
-
control within

Spring
Security. If you don't you can skip it and come back to it later, as this section is only really relevant

for people who
need to do some customization in order to use more than
simple role
-
based security.


When you use a namespace configuration, a default instance of
AccessDecisionManager
is

automatically
registered for you and will be used for making access decisions for method invocations and

web URL access, based
on the access

attributes you specify in your
intercept
-
url
and
protectpointcut

declarations (and in
annotations if you are using annotation secured methods).


The default strategy is to use an
AffirmativeBased AccessDecisionManager
with a

RoleVoter and an XYZ.

@IfAnyRo
le()

@IfAllRoles()

@IfNotAnyRole()

Expression Based Access Control

Spring Security 3.0 introduced the ability to use Spring EL expressions as an authorization mechanism in addition to
the simple use of configuration attributes and access
-
decision voters wh
ich have seen before.

Expression
-
based
access control is built on the same architecture but allows complicated boolean logic to be encapsulated in a single
expression.


Spring Security uses Spring EL for expression support and you should look at how that
works if you are interested
in understanding the topic in more depth.

Expressions are evaluated with a
“root object”

as part of the evaluation
context.

Spring Security uses specific classes for web and method security as the root object, in order to prov
ide
built
-
in expressions and access to values such as the current principal.


The base class for expression root objects is
SecurityExpressionRoot
.

This provides some common
expressions which are available in both web and method security.

Table

15.1.

Comm
on built
-
in expressions

Expression

Description

hasRole([role])

Returns
true

if the current principal has the specified role.

hasAnyRole([role1,role2])

Returns
true

if the current principal has any of the supplied roles (given as a
comma
-
separated list of

strings)

principal

Allows direct access to the principal object representing the current user

authentication

Allows direct access to the current
Authentication

object obtained from the
SecurityContext

permitAll

Always evaluates to
true

Page
7

of
16

Expression

Description

denyAll

Always
evaluates to
false

isAnonymous()

Returns
true

if the current principal is an anonymous user

isRememberMe()

Returns
true

if the current principal is a remember
-
me user

isAuthenticated()

Returns
true

if the user is not anonymous

isFullyAuthenticated()

Re
turns
true

if the user is not an anonymous or a remember
-
me user

Managing Authentication

This is the job of the AuthenticationManager. It is a globally available bean that aids in converting passwords, etc,
and then maintains the SecurityContext on a per
-
session basis. From this object, you can determine the logged
-
in
user.


This is configured using the following XML:

<
http

use
-
expressions=
"true"
>


<intercept
-
url pattern=
"/login"

access=
"permitAll()"

/>


<intercept
-
url pattern=
"/resources/**"

acces
s=
"permitAll()"

/>


<intercept
-
url pattern=
"/**"

access=
"isAuthenticated()"

/>


<form
-
login login
-
page=
"/login"



authentication
-
failure
-
url=
"/login?
login_error
=1"

/>


<logout />


<remember
-
me />




<session
-
management>


<concurrency
-
control max
-
sessions=
"1"

expired
-
url=
"/login?error=expired"
/>


</session
-
management>

</
http
>


The most
-
important specs here are the control specs


intercept url.


The second
-
most
-
important specs here at the login and log out managem
ent specs.


Within the SecurityContext a user also has a set of SecurityRoles.


The AuthenticationManager also handles login, rememberMe, and more.

Reading from LDAP

To use
LDAP
-
based authentication, we’ll first need to use Spring Security’s
LDAP
module an
d configure
LDAP
authentication within the Spring application context.

When it comes to configuring
LDAP
authentication, we have
two choices:


With an
LDAP
-
oriented authentication provider


With an
LDAP
-
oriented user service


For the most part, it’s a
n even choice on which you should use.


But there are some small considerations to make when choosing one over the other.


For the in
-
memory and
JDBC
-
based user services, we declared an
<authentication
-
provider>
and wired in
the user service.

We can do
the same thing for an
LDAP
-
oriented user service.

But a more direct way is to use a
special
LDAP
-
oriented authentication provider by declaring an
<ldap
-

authentication
-
provider>
within
the
<authentication
-
manager>
:


<authentication
-
manageralias="authenti
cationManager">


<ldap
-
authentication
-
provider


user
-
search
-
filter="(uid={0})" group
-
search
-
filter="member={0}"/>

Page
8

of
16

</authentication
-
manager>


The
user
-
search
-
filter
and
group
-
search
-
filter
attributes are used to provide a filter for the base
LDAP
q
ueries, which are used to search for users and groups. By default, the base queries for both users and groups
are empty, indicating that the search will be done from the root of the
LDAP
hierarchy. But we can change that by
specifying a query base:


<ldap
-
user
-
serviceid="userService"


user
-
search
-
base="ou=people" user
-
search
-
filter="(uid={0})"


group
-
search
-
base="ou=groups" group
-
search
-
filter="member={0}"/>


The
user
-
search
-
base
attribute provides a base query for finding users. Likewise, the
group
-
search
-
base
specifies the base query for finding groups. Rather than search from the root, we’ve specified that users be searched
for where the organization unit is
people
. And groups should be searched for where the organizational unit is
groups
.

Securi
ng Method Calls

Method security is a bit more complicated than a simple allow or deny rule.


Spring Security 3.0 introduced some
new annotations in order to allow comprehensive support for the use of expressions.

@Pre

and
@Post

Annotations

There are four a
nnotations which support expression attributes to allow pre and post
-
invocation authorization checks
and also to support filtering of submitted collection arguments or return values.

They are
@PreAuthorize
,
@PreFilter
,
@PostAuthorize

and
@PostFilter
.

The
ir use is enabled through the
global
-
method
-
security

namespace element:

<global
-
method
-
security pre
-
post
-
annotations="enabled"/>

Access Control using
@PreAuthorize

and
@PostAuthorize

The most obviously useful annotation is
@PreAuthorize

which decides wheth
er a method can actually be
invoked or not. For example (from the
“Contacts”

sample application)


@PreAuthorize("hasRole('ROLE_USER')")



public void create(Contact contact);

which means that access will only be allowed for users with the role "ROLE_USER"
. Obviously the same thing
could easily be achieved using a traditional configuration and a simple configuration attribute for the required role.
But what about:


@PreAuthorize("hasPermission(#contact, 'admin')")



public void deletePermission(Contact con
tact,


Sid recipient, Permission permission);

Here we're actually using a method argument as part of the expression to decide whether the current user has the
“admin”
permission for the given contact. The built
-
in
hasPermission()

expr
ession is linked into the Spring
Security ACL module through the application context,
which is discussed in a section below
.

You can access any of
the method arguments by name as expression variables, provided your code has debug information compiled in.

Any Spring
-
EL functionality is available within the expression, so you can also access properties on the arguments.

For example, if you wanted a particular method to only allow access to a user whose username matched that of the
contact, you could write


@PreAuthorize("#contact.name == authentication.name")


public void doSomething(Contact contact);

Here we are accessing another built

in expression,
authentication
, which is the
Authentication

stored in the security context.

You can also access its
“pri
ncipal”

property directly, using the expression
principal
.

The value will often be a
UserDetails

instance, so you might use an expression like
principal.username

or
principal.enabled
.

Page
9

of
16


Less commonly, you may wish to perform an access
-
control check after t
he method has been invoked.

This can be
achieved using the
@PostAuthorize

annotation.

To access the return value from a method, use the built

in
name
returnObject

in the expression.

Filtering using
@PreFilter

and
@PostFilter

As you may already be aware,
Spring Security supports filtering of collections and arrays and this can now be
achieved using expressions. This is most commonly performed on the return value of a method. For example:


@PreAuthorize("hasRole('ROLE_USER')")


@PostFilter("hasPermission(
filterObject, 'read') or hasPermission(filterObject,
'admin')")


public List<Contact> getAll();

When using the
@PostFilter

annotation, Spring Security iterates through the returned collection and removes
any elements for which the supplied expression is f
alse. The name
filterObject

refers to the current object in
the collection. You can also filter before the method call, using
@PreFilter
, though this is a less common
requirement. The syntax is just the same, but if there is more than one argument which is

a collection type then you
have to select one by name using the
filterTarget

property of this annotation.


Note that filtering is obviously not a substitute for tuning your data retrieval queries. If you are filtering large
collections and removing many o
f the entries then this is likely to be inefficient.

Using Declarative Specifications

public interface
BankService {


@Secured("IS_AUTHENTICATED_ANONYMOUSLY")


public
Account readAccount(Long id);


@Secured("IS_AUTHENTICATED_ANONYMOUSLY")


public
Accou
nt[] findAccounts();


@Secured("ROLE_TELLER")


public
Account post(Account account,
double
amount);

}


There are also a set of tags that make calls to the AccessDecisionManager.

Built
-
In Expressions

There are some built
-
in expressions which are specific
to method security, which we have already seen in use above.
The
filterTarget

and
returnValue

values are simple enough, but the use of the
hasPermission()

expression warrants a closer look.

The
PermissionEvaluator

interface

hasPermission()

expressions are
delegated to an instance of
PermissionEvaluator
. It is intended to
bridge between the expression system and Spring Security's ACL system, allowing you to specify authorization
constraints on domain objects, based on abstract permissions. It has no explicit

dependencies on the ACL module, so
you could swap that out for an alternative implementation if required. The interface has two methods:


boolean

hasPermission(Authentication authentication, Object targetDomainObject,
Object permission);



boolean

hasP
ermission(Authentication authentication, Serializable targetId, String
targetType, Object permission);

which map directly to the available versions of the expression, with the exception that the first argument (the
Authentication

object) is not supplied. T
he first is used in situations where the domain object, to which
access is being controlled, is already loaded. Then expression will return true if the current user has the given
permission for that object. The second version is used in cases where the obj
ect is not loaded, but its identifier is
known. An abstract
“type”

specifier for the domain object is also required, allowing the correct ACL permissions to
Page
10

of
16

be loaded. This has traditionally been the Java class of the object, but does not have to be as lon
g as it is consistent
with how the permissions are loaded.


To use
hasPermission()

expressions, you have to explicitly configure a
PermissionEvaluator

in
your application context. This would look something like this:


<security:global
-
method
-
security

pre
-
post
-
annotations
=
"enabled"
>


<security:expression
-
handler

ref
=
"expressionHandler"
/>


</security:global
-
method
-
security>



<bean

id
=
"expressionHandler"


class
=
"org.springframework.security.access.expression.method.DefaultMethodSecurityExpr
essionHa
ndler"
>


<property

name
=
"permissionEvaluator"

ref
=
"myPermissionEvaluator"
/>


</bean>

Where
myPermissionEvaluator

is the bean which implements
PermissionEvaluator
. Usually
this will be the implementation from the ACL module which is called
AclPermis
sionEvaluator
. See the
“Contacts”

sample application configuration for more details.

Forwarding to
an
error screen

There is an example of this in QbeFit.


<
http

use
-
expressions
=
"true"

access
-
denied
-
page
=
"/accessDenied"
>

</http>


This goes to an action:



@RequestMapping
(value =
"/accessDenied"
)


public

String special2() {


return

"accessDenied"
;


}


This view is processed by the Tiles system to create
a view with a header and footer (it might be a special header or
footer).

Using Access Control Lists

http://grzegorzborkowski.blogspot.com/2008/10/spring
-
security
-
acl
-
very
-
basic
-
tutorial.ht ml


Imagine the following scenario.

We have a company.

Eac
h employee in this company is obliged to provide some
work reports to his manager.

Manager is allowed to accept the report (or not
-

but this is not relevant here).

Only
employee can create report.

Only manager can accept it.

So far it's easy and can b
e solved with roles
-
based
solution.

The key point, however, is that manager can't accept all reports
-

only reports submitted by his subordinate
employee.

Let's say we have four employees and 2 managers.

Employees empl1 and empl2 are assigned to
manager
1, and empl3 and empl4 are assigned to manager2.

So manager1 can only accept reports of empl1 and
empl2, but not those of empl3 and empl4.

This cannot be easily solved with roles. Instead, we will use Spring
Security ACLs.


Spring Security 3.0 focuses on

the use of expression
-
language as an alternative to the older voter
-
based mechanism.
The latter is still fully supported. This allows security access rules to be easily defined in terms of the current
invocation context without the use of custom code. U
sing this approach you can define your access constraints
using multiple factors


user identity, time of day, authorities held, method being invoked, method arguments,
specific properties on method arguments or any other syntax supported by Spring
-
EL.


Do
main object instance security:

In many applications it's desirable to define Access Control Lists (ACLs) for
individual domain object instances. We provide a comprehensive ACL package with features including integer bit
Page
11

of
16

masking, permission inheritance (inc
luding blocking), an optimized JDBC
-
backed ACL repository, caching and a
pluggable, interface
-
driven design.


Spring Security's ACL services are shipped in the
spring
-
security
-
acl
-
xxx.jar
. You will

need to add
this JAR to your classpath to use Spring Secur
ity's domain object instance security

capabilities.


Given databases are central to the o
peration of the ACL module, let's explore the four main tables used

by
default in the implementation. The tables are presented below in order of size in a typical Spri
ng

Security ACL
deployment, with the table with the most rows listed last:



(like User)
ACL_SID allows us to uniquely identify any principal or authority in the system ("SID" stands
for "security identity"). The only columns are the ID, a textual representa
tion of the SID, and a flag to
indicate whether the textual representation refers to a principal name or a
GrantedAuthority
. Thus,
there is a single row for each unique principal or
GrantedAuthority
. When used in the context of
receiving a permission, a S
ID is generally called a "recipient".



(Like EntityType) ACL_CLASS allows us to uniquely identify any domain object class in the system. The
only columns are the ID and the Java class name. Thus, there is a single row for each unique Class we wish
to store
ACL permissions for.



(no ObjectReference
) ACL_OBJECT_IDENTITY stores information for each unique domain object
instance in the system. Columns include the ID, a foreign key to the ACL_CLASS table, a unique
identifier so we know which ACL_CLASS instance we
're providing information for, the parent, a foreign
key to the ACL_SID table to represent the owner of the domain object instance, and whether we allow
ACL entries to inherit from any parent ACL. We have a single row for every domain object instance we're

storing ACL permissions for.



(like Permission) Finally, ACL_ENTRY stores the individual permissions assigned to each recipient.
Columns include a foreign key to the ACL_OBJECT_IDENTITY, the recipient (ie a foreign key to
ACL_SID), whether we'll be auditi
ng or not, and the integer bit mask that represents the actual permission
being granted or denied. We have a single row for every recipient that receives a permission to work with a
domain object.


Page
12

of
16

Two samples ship with Spring Security that demonstrate th
e ACL mo
dule.

The first is the Contacts
Sample, and the
other is the Document Management System (DMS) Sample.

We suggest taking a look

over these for examples.

Using Spring Security in
Grails

Grails developers can use Spring Security through a plug
-
in th
at contains the library and a set of Grails
-
based
wrappers.
The current version is 1.2.6, released in December 2011
, however, since that depends upon Spring
Security 3.0.7 which depends upon Spring 3.0.6, we are using version 1.2.4
.
That version of the
p
lug
-
in (at least at
the core level) contains the following libraries
:


Groovy classes
supplied
:


Installation

The first step is to install the plugin, then run the script “s2
-
quickstart” to create the needed classes and update the
configuration files.

T
his in turn, adds the release and webxml plugins. The syntax of the s2
-
quickstart is:


Usage: grails s2
-
quickstart <domain
-
class
-
package> <user
-
class
-
name> <role
-
class
-
name>
[requestmap
-
class
-
name]


Creates a user and role class (and optionally a requestm
ap class) in the specified
package


Example: grails s2
-
quickstart com.yourapp User Role

Example: grails s2
-
quickstart com.yourapp Person Authority Requestmap


See the discussion in “Grails in Action” for more information.

Basic Configuration

The

Spring Sec
urity plugin maintains its configuration in the standard
Config.groovy

file.

Default values are in
the plugin's
grails
-
app/conf/DefaultSecurityConfig.groovy

file, and you add application
-
specific
values to the
grails
-
app/conf/Config.groovy

file.

The two
configurations will be merged, with
application values overriding the defaults.


This structure enables environment
-
specific configuration such as, for example, fewer structure
-
restrictive security
rules during development than in production.

Like any env
ironment
-
specific configuration parameters, you wrap
them in an
environments

block.


The settings added by the “s2
-
quickstart” script are:


// Added by the Spring Security Core
plugin
:

grails
.
plugins
.
springsecurity
.
userLookup
.
userDomainClassName

=
'com.inc
ra.User'

grails
.
plugins
.
springsecurity
.
authority
.
className

=
'com.incra.Role'

grails
.
plugins
.
springsecurity
.
userLookup
.
authorityJoinClassName

=
'com.incra.UserRole'


Page
13

of
16

The commonly
-
applied configuration include:


grails
.
plugins
.
springsecurity
.
rememberMe
.
pers
istent

=
true

grails
.
plugins
.
springsecurity
.
rememberMe
.
persistentToken
.
domainClassName

=
'com.incra.PersistentLogin'


Then you need to indicate how the security rules are being set up. By default, annotation
-
based authorization is
used, how this can be ch
anged as follows:


grails
.
plugins
.
springsecurity
.
securityConfigType

=
"InterceptUrlMap"

grails.plugins.springsecurity.interceptUrlMap = [


'/secure/**': ['ROLE_ADMIN'],


'/finance/**': ['ROLE_FINANCE', 'IS_AUTHENTICATED_FULLY'],


'/js/**':

['IS_AUTHENTICATED_ANONYMOUSLY'],


'/css/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],


'/images/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],


'/*': ['IS_AUTHENTICATED_ANONYMOUSLY'],


'/login/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],


'
/logout/**': ['IS_AUTHENTICATED_ANONYMOUSLY']

]

Hierarchical Roles

Hierarchical roles are a convenient way to reduce clutter in your request mappings.


For example, if you have several types of 'admin' roles that can be used to access a URL pattern and
you do not use
hierarchical roles, you need to specify all the admin roles:


package

com.mycompany.myapp


import

grails.plugins.springsecurity.Secured


class SomeController {


@Secured(['ROLE_ADMIN', 'ROLE_FINANCE_ADMIN', 'ROLE_SUPERADMIN'])


def someA
ction = {





}

}


However, if you have a business rule that says
ROLE_FINANCE_ADMIN

implies being granted
ROLE_ADMIN
,
and that
ROLE_SUPERADMIN

implies being granted
ROLE_FINANCE_ADMIN
, you can express that
hierarchy as:


grails.plugins.springsecuri
ty.roleHierarchy = '''


ROLE_SUPERADMIN > ROLE_FINANCE_ADMIN


ROLE_FINANCE_ADMIN > ROLE_ADMIN

'''


Then you can simplify your mappings by specifying only the roles that are required:


package

com.mycompany.myapp


import

grails.plugins.springsecurity.Se
cured


class SomeController {


@Secured(['ROLE_ADMIN'])


def someAction = {





}

}

Page
14

of
16


You can also reduce the number of granted roles in the database.

Where previously you had to grant
ROLE_SUPERADMIN
,
ROLE_FINANCE_ADMIN
, and
ROLE_ADMIN
, now you

only need to grant
ROLE_SUPERADMIN
.

Advanced Configuration

There are a series of callback events available from Spring Security. The most important ones allow you to take
action upon authorization success or failure.
As mentioned in Chapter 5 of the us
er guide you need to enable events
with "useSecurityEventListener" and configure one or more callback closures, e.g.:


grails.plugins.springsecurity.useSecurityEventListener = true


grails.plugins.springsecurity.onInteractiveAuthenticationSuccessEvent = {
e, appCtx
-
>


println "onInteractiveAuthenticationSuccessEvent: $e"

}


grails.plugins.springsecurity.onAbstractAuthenticationFailureEvent = { e, appCtx
-
>


println "onAbstractAuthenticationFailureEvent: $e"

}


grails.plugins.springsecurity.onAuthentica
tionSuccessEvent = { e, appCtx
-
>


println "onAuthenticationSuccessEvent: $e"

}


grails.plugins.springsecurity.onAuthenticationSwitchUserEvent = { e, appCtx
-
>


println "onAuthenticationSwitchUserEvent: $e"

}

Custom Authentication Decision

Authenticat
ion decisions are made by the UserDetailsService within the plugin. By default, it will fetch against the
database for the entities that represent the user and role information, using the domain classes that were created in
the s2
-
quickstart script.


The
plugin provides
org.codehaus.groovy.grails.plugins.springsecurity.GormUserDetailsService

as its
UserDetailsService

implementation and
org.codehaus.groovy.grails.plugins.springsecurity.GrailsUser

(which extends Spring Security's
User
) as its
UserDetails

imp
lementation.


To allow for a different approach (such as when the user role information is not in a table that is joined to the user
table), y
ou can extend or replace
GormUserDetailsService

with your own implementation by defining a bean
in
grails
-
app/conf
/spring/resources.groovy

(or
resources.xml
) with the same bean name,
userDetailsService
.


Here is an example:


public

class

MyUserDetailsService
implements

UserDetailsService {



/**


* Create a subclass of UserDetails for this
username


*/



UserDetails loadUserByUsername(String username)


throws

UsernameNotFoundException, DataAccessException {


User.
withTransaction

{


User user = User.
findByUsernameAndEnabled
(username,
true
)



if

(user) {

Page
15

of
16



GrantedAuthority[] authorities = loadAuthorities(user, username)



return

new

GrailsUser(


username, user.
password
, user.
enabled
,


true
,
true
,
true
, authorities
as

List, user.
id
)


}
else

{



throw

new

UsernameNotFoundException(
"No user with login: ${username} found"
)


}


}


}



/**


* Support method to find the roles for this user.


*/


protected

GrantedAuthority[] loadAuthorities(User user, Strin
g username) {


List<UserRole> userRoleList = UserRole.
findAllByUser
(user);



return

userRoleList.
collect

{ userRole
-
>


new

GrantedAuthorityImpl(userRole.
role
.
authority
)


}
as

GrantedAuthority[]


}

}


The lookup code is w
rapped in a
withTransaction

block to avoid lazy loading exceptions when accessing
the
authorities

collection. There are obviously no database updates here but this is a convenient way to keep
the Hibernate
Session

open to enable accessing the roles.


To us
e your implementation, register it in
grails
-
app/conf/spring/resources.groovy

like this:


beans = {


userDetailsService(com.mycompany.myapp.MyUserDetailsService)

}


You could also extend the UserDetails object which is used, to have additional informatio
n. For example
GrailsUser

already adds the
id

value from the domain class to so we can do a more efficient database load of
the user.


If all you have is the username, then you need to call
User.findByUsername(principal.username)
,
but if you have the id y
ou can call
User.get(principal.id)
which is faster because it is against the primary key.
You could add additional fields such as “fullName”, geographic region of user, or others will reduce the need to
fetch user information from the database on
each requ
est processing cycle
.


Another option for loading users and roles from the database is to subclass
org.codehaus.groovy.grails.plugins.springsecurity.GormUserDetailsService

-

the methods are
all protected so you can override as needed.


Finally,
If you stor
e mutable data in your custom
UserDetails

implementation (such as full name in the
preceding example), be sure to rebuild the
Authentication

if it changes.

springSecurityService

has a
reauthenticate

method that does this for you:


class MyController {


def springSecurityService



def someAction {


def user = …


// update user data


user.save()


sprin
gSecurityService.reauthenticate(
user.username
)





}

Page
16

of
16

}

Open Questions/Issues

How to set up an access denied handler?


http://for
um.springsource.org/showthread.php?57373
-
How
-
to
-
replace
-
form
-
login

Appendix

A: Example Programs that are based
on
Spring Security

SP01


no S
pring Security

usage

SP02


contains a minimal configuration of spring security

SP03


much more detailed, includi
ng a custom login form, and limited access rules

QbeFit


contains a real
-
world configuration, including
the use of <sec:authorize> tags

GR04


Grails program using the latest version of the Grails plug
-
in.