Spring Security: Expression-Based Access Control

SFL
SFL Newsroom
Published in
7 min readJul 27, 2018

Spring Security provides comprehensive security services for Java EE-based enterprise software applications. It currently supports authentication integration with many technologies:

Before we dive deeper into the subject, it’s worth taking a look at how Spring Security evolved.

Spring Security began in late 2003 as “The Acegi Security System for Spring”. At the time the Spring community was relatively small a simple security implementation was built and not released. The 1.0.0 final release was published in May 2006 — after more than two and a half years of active use in numerous production software projects and many hundreds of improvements and community contributions. Acegi Security became an official Spring Portfolio project towards the end of 2007 and was rebranded as “Spring Security”.

Now, let’s pass on to how it can be used to make your life easier ;)

Spring Security Application Scenarios

In business cases, we often have roles and permissions. The product owner may have certain requirements regarding these permissions, like who can edit stuff, which parts of a given project can a user type see and more. This is especially complicated if we have a multitenant project where the users of one organization shouldn’t have access to the data of another company. At the same time the system has to be devoid of authorized data manipulations.

The requirements may be very varied and complex so as a result, we have to offer a solution that has to manage these issues.

Our problem is to check if authority (executing user) has corresponding access rights for the action.

How do we solve this problem? Well, there is a number of solutions, let’s talk about some of them:

  • Do nothing

We can rely on the assumption that frontend has restricted unauthorized calls. Obviously, this is not the best decision.

  • Check permission in every method

We can add checks in all methods manually like: someClass().getUser().getId().equals(user.getId());

This is a very widely spread approach, but it results in code redundancy, reduced scalability and increased need for test coverage.

  • Write security context manually

We can TRY to write our own security context using annotations. But with Spring Security around since 2003, concurrency will be pretty hard, as this process is very complicated and full of bugs.

  • Use Spring Security

We can just use Spring Security 4 Method Security Expressions

Advantages of using Spring Security Expression-Based Access Control

  • Safety

Users of one organization can not view (especially modify) other’s data

  • No Code redundancy & Waste of time

You never write the same checking in every method avoiding tons of code, redundant test scenarios and more

  • Cleaner, configurable and flexible Code

You can always configure to turn on/off the Spring security by just an xml file without much effort, e.g. you can fully omit the security staff in admin

  • Complicated logic in a single expression

Expression-based access control allows complicated Boolean logic to be encapsulated in a single expression

Application

Now that the advantages have driven you to opting for Spring security, let’s have a look at some points regarding expression-based access control:

So, the here are the main components we will deal with:

  • Use boolean Spring EL Expressions to define access rules (e.g. subject.project.id == resource.project.id) which will be stored in a central repository (e.g. memory, database, LDAP, file).
  • Define a centralized component that loads the rules, wrap the elements of access context, and evaluate the rules’ expressions to decide whether access is granted or denied.
  • Use the Spring annotations — @PreAuthorize(“hasPermision(…)”),

@PostAuthorize(“hasPermision(…)”)

to enforce the access rules.

An example we have on Service Methods would be:

As a result, any access request will have four elements:

  • Subject

This is the entity (mostly a user) that requests access.

  • Resource

This stands for the entity to be accessed (e.g. file, database record, Store Information, …)

  • Action

This refers to operation to be carried out on the resource (e.g. read, write, delete, …)

  • Environment

Any information regarding the context of the access that might be used in making the access decision (e.g. time, network, etc.)

Proceeding to SpEL, which is pretty easy to grasp:

As stated above we will need some Spring EL expressions to evaluate our security logic. SpEL stands for Spring Expression Language and is a powerful expression language that supports querying and manipulating an object graph at runtime. It can be used with XML or annotation-based Spring configurations.

There are several operations available in the language:

Expressions root objects base class is SecurityExpressionRoot

The base class for expression root objects is SecurityExpressionRoot. This provides some common built-in expressions which are available in both web and method security.

We will mostly use hasPermission expression as it’s most suitable for method security. Method security is a bit more complicated than a simple allow or deny rule. Spring Security 3.0 introduced these annotations in order to allow comprehensive support for the use of expressions. Moreover we can implement new security expression ourselves in case the existing ones are not sufficient for our use cases.

Getting around Permission evaluator

This is the entry point for ABAC (Attribute-based access control) logic to be executed. All access decisions made by Spring Security framework (Expression-Based Access Control) are delegated to this component.

hasPermission() expressions are delegated to an instance of PermissionEvaluator. It is intended to bridge the expression system and Spring Security’s ACL system, allowing you to specify authorization constraints on domain objects, based on abstract permissions. The interface has two methods correspondingly:

To use hasPermission() expressions, you have to explicitly configure a PermissionEvaluator in your application context. This would look something like this:

Where myPermissionEvaluator is the bean which implements PermissionEvaluator. As stated above this is the entry point for our security logic and here we should implement hasPermission methods to evaluate our security expression.

@Pre and @Post Annotations

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

The most obviously useful annotation is @PreAuthorize which decides whether a method can actually be invoked or not

Let’s see a simple example. Here the access to this method will only be allowed for users with the role “ROLE_USER”

@PreAuthorize(“hasRole(‘USER’)”)

public List<Contact> getAll();

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.

@PreAuthorize(“hasPermission(#contact, ‘admin’)”)
public void deletePermission(Contact contact, Sid recipient, Permission permission);

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. When using the @PostFilter annotation, Spring Security iterates through the returned collection and removes any elements for which the supplied expression is false. The name filterObject refers to the current object in the collection.

@PreAuthorize(“hasRole(‘USER’)”)

@PostFilter(“hasPermission(filterObject, ‘read’) or hasPermission(filterObject, ‘admin’)”)

public List<Contact> getAll();

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

@PreAuthorize is the most widely used one (around 90% of cases). Before appearing in your service method, we have an authorization step.

Service Methods using Spring Security expression evaluation

Let’s see a couple of simple Spring Security expressions used in our project:

This is a pretty simple way of solving the problem with role management without having code redundancy and overcomplicating our service methods’ logic. As it often happens in programming, there’s a simple way for handling complicated stuff, and Spring Security is one such way!

About this author:

Mary Mirzoyan is a Java Engineer, BI pro and constant learner.

Let’s talk!

--

--