Introduction to Spring Security

Using Spring Security is like the blessing. Everything is coded and you only need to implement it correctly. But always is good to know what we are implementing. This is the main purpose of this article, to understand how one of particular Spring Security modes, ACL, works.

The article will be divided on two parts. The first one will cover theoretical concepts of ACL and Spring Security ACL project. It will present the key concepts of the project. At the second part, we will see how these thoughts are implemented in the code, in which packages and names.

Key concepts of Spring Security ACL

Before analyzing Spring Security project, let's start by understanding what is ACL ? ACL acronym means access control list. This is a list of permissions between objects and users. Thanks to these links we can determine which actions one user can do on the objects stored in the system. For example, we can check if a user with login user2 is able to modify an article entitled "Private rapport of activity 2013". We can draw a table to illustrate that :

Permissions to article "Private rapport of activity 2013" :
User Can read Can modify Can delete
user1 Yes No No
user2 Yes No No
user3 Yes Yes No

As we can see, user1 and user2 can only read the article. The last user can read and modify it. So, we can consider Spring Security ACL project as a programming implementation of above table.

In Spring Security ACL we can distinguish following actors :

A lot of concepts are similar. For example, permission evaluator and voter, both decide if a user can access to a protected element. But in the second part of this article, we'll see the exact decision flow in Spring Security ACL.

Spring Security ACL permission flow

Before starting to talk about Spring Security ACL components, let's take a look to a simplified schema of steps which are done every time when a security identity tries to execute protected method.

  1. Roles hierarchy initialization

    First, when servlet container starts, Spring initializes the beans defined in our configuration. We can observe the initialization of AclService, LookupStrategy, AuthorizationStrategy and RoleHierarchy implementations. The most interesting is the last one which constructs a tree of roles. The tree is made thanks to character > which defines the roles reachables from a parent role. For example, ROLE_ADMIN > ROLE_USER > ROLE_VISITOR means that ROLE_ADMIN encapsulates two following roles (ROLE_USER and ROLE_VISITOR) and that ROLE_USER encapsulates only ROLE_VISITOR. In practice, that means that security identity with the ROLE_ADMIN will be able to see the content reserved to ROLE_USER. But in another side, ROLE_VISITOR won't be able to see this content because it doesn't encapsulate ROLE_USER.

  2. Expression treatment.

    Imagine the following expression :

    @PostAuthorize("hasPermission(returnObject, 'READ')")
    public Article getArticle(int id);

    It means that the method will return the instance of Article class only if security identity has a permission to read it. How it works under hood ?

    In this case, the implementation of MethodSecurityExpressionHandler, defined as the bean with id expressionHandler, is invoked. An expression handler is a class which treats the expression included in ACL annotations (@PostAuthorize, @PreAuthorize). It gets all of needed objects to evaluate if a user can call a secured method. Among these objects, we can find: the permission evaluator, roles hierarchy, authentified user, the method protected by the expression and a trust resolver.

  3. Evaluator checks the permissions.

    Now, it's the turn of permission evaluator to make a choice if the security identity can invoke a protected method. It does it by calling the same function as the function defined in security expression. In our example, it will be the method hasPermission. The permission check is made thanks to AclService implementation which verify in the datasource (for exemple: database), if a user can call secured method.

    To make this check, AclService will demand a support of LookupStrategy implementation. The lookup strategy will return an access control entry.

    At the end, permission evaluator verifies if security identity has a granted access to a secured resource by invoking isGranted() method of permission granting strategy. The result of this method is transmitted into permission evalutor. Thanks to that, it can send true if authorization occurs correctly and false if the authorization fails for the security identity.

Key classes of Spring Security ACL

In the previous part we saw some of methods used in authorization process. Now, we will see some of key classes and interfaces in Spring Security ACL infrastructure :

Voters and permission evaluator

You are certainly a little bit troubled about the existence of two ways of authorizing somebody. As we can saw in the previous parts, voter plays the same role as permission evaluator. But they are some of subtle difference between them. Firstly, the architecture. Even if we can extend the voter as we want, it seems to be less evolved and flexible than permission evaluator. In fact, it will be harder to parse hasPermission expression by the voter. More, a lot of parsing code must be written by the programmer.

In additionally, the voter is the object more adapted to static checks, based for example on prefixed names like ROLE_*, IS_* etc. The invocation of these protections seems to be more weaker than the same invocation made by permission evaluator. The last invocation must pass by an expression handler.

Thirdly, the voter can't be used with the pre-post annotations. When we need to check if object returned by a method can be accessed by the user, @PostAuthorize annotation will be the only solution. To handle it, we'll need to pass by permission evaluator rather than by the roles.

And the last visible difference is the fact that the voter needs generally the help of an access decision manager (ADM). An access decision manager is a container of voters which, regarding of chosen scenario (affirmative, consensus, unanimous), allows or disallows access to a protected resource. And if one access decision manager is set, Spring will call it to check user's access permissions. ADM will iterate through every known voter and check if the voter allows the access. Permission evaluator goes directly to the goal without checking unusable decision makers.

In this article we discovered how Spring Security authorization (ACL) process works. The first part presented the theoretical concepts of authorization, with the list of authorization actors. In the next part, we saw the authorization flow in Spring Security project. The third one talked a little bit more about the project's key classes. At the end we learned which were the differences between two similar authorization ideas : role and permission evaluator.


If you liked it, you should read:

📚 Newsletter Get new posts, recommended reading and other exclusive information every week. SPAM free - no 3rd party ads, only the information about waitingforcode!