Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security entity field level security

I have a Spring MVC application which presents a view which shows all of the fields from a Customer entity such as name, address, phone number etc. The application has various roles such as ROLE_USER and ROLE_ADMIN. Users with ROLE_USER are only able to see the customer name where as users with ROLE_ADMIN can see all of the customer fields.

At the moment the way I have implemented this is with a Thymeleaf view which makes use of the SpringSecurityDialect to restrict access to certain fields based on the user's role:

<th:block sec:authorize="hasRole('ROLE_ADMIN')">
  <div th:text="${customer.phoneNumber}" />
</th:block>

Whilst this works absolutely fine it doesn't feel right and it's difficult to test. I would like to write tests against the controller which call the controller method with a principal that has different roles such as testViewCustomerAsRoleAdmin and testViewCustomerAsRoleUser. This isn't possible to verify as the controller returns a Customer to the view which is fully populated and has every field accessible via the getters.

What I'm after is some sort of field level security at the entity level where I can make use of the Spring Security annotations:

@PreAuthorize("hasRole('ROLE_ADMIN')")
public String getPhoneNumber()
{
  return phoneNumber;
}

It would be ideal if this could then raise an AccessDeniedException when trying to access the field if the principal is not authorized.

The Jersey project seems to have this sort of concept which is mentioned here, here and an example here. It does however seem to be limited to role based security rather than the full SpEL support offered with @PreAuthorize

Is there any way or implementing this sort of thing with Spring Security, I know the security context or SpEL evaluation context is not available in entities as they are not Spring managed. If not, is there any other approach which might allow me to achieve the same thing?

EDIT:

I don't know the Spring Security framework inside out but it seems like something that might be able to be done using Spring AOP in ApectJ mode to instrument methods of domain (entity) classes. It would then be a case of getting hold of the AccessDecisionManager and passing along the authentication (presumably obtained from the SecurityContextHolder) along with the contents of the annotation on the domain class methods (if present). Does anyone have experience with doing this sort of thing?

like image 268
Robert Hunt Avatar asked Jul 15 '15 22:07

Robert Hunt


People also ask

What are the level of security in spring?

Simply put, Spring Security supports authorization semantics at the method level. Typically, we could secure our service layer by, for example, restricting which roles are able to execute a particular method — and test it using dedicated method-level security test support.

What is hasRole and hasAnyRole?

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)

How does Spring support method level security?

Method-level security is implemented by placing the @PreAuthorize annotation on controller methods (actually one of a set of annotations available, but the most commonly used). This annotation contains a Spring Expression Language (SpEL) snippet that is assessed to determine if the request should be authenticated.


1 Answers

I've managed to solve the problem using Spring AOP in AspectJ mode. The various Spring annotations such as @Transactional and @PreAuthorize will work on any non-Spring managed classes if you enable AspectJ mode and perform either compile time or load time weaving, there is a very good example here: https://github.com/spring-projects/spring-security/tree/4.0.1.RELEASE/samples/aspectj-jc

You need to make sure you have the spring-security-aspects dependency in your project (or plugin if you're using compile-time weaving) to enable weaving of @Secured annotations. Despite the comment in AnnotationSecurityAspect which describes the class as:

Concrete AspectJ aspect using Spring Security @Secured annotation for JDK 1.5+.

The class does actually weave the other Spring annotations including @PreAuthorize, @PreFilter, @PostAuthorize and @PostFilter.

like image 162
Robert Hunt Avatar answered Sep 18 '22 20:09

Robert Hunt