Frage

I am working on a Spring web application that uses:

  • Spring MVC
  • Spring Core
  • Spring Roo
  • Spring Security
  • Spring Data JPA
  • Mysql

The issue I have is as follows: for each access from the web layer to the application's entities/objects I want to be able to check whether or not they do indeed belong to the current user.

Let me illustrate: users of the application have advertisements, curriculums (referred to as entities/objects). I frequently perform GETs or POSTs on those objects/entities using the PK/ID in order to retrieve, update or delete those objects. As of now, I have not found a clean and flexible way to prevent a user from retrieving, updating or deleting someone else's objects.

I use Spring Security and I know at any time who is the current user (currently logged-in user/principal) but I am not sure where (which layer) and how to perform the check.

I have tried advising the service and controller methods with AspectJ but the way I implemented it is far from ideal as a mere change in the method signature causes the advice not to be applied.

I could use ACLs with Spring Security but it adds an unnecessary layer of complexity: I just need to grant or reject access to the entities given on whether or not they belong to an account/user.

Can anyone who has already met this issue please provide a clean, flexible and DRY solution?

War es hilfreich?

Lösung

In my mind this is an authorisation problem. Essentially you want to confirm that the current user has the correct permissions to perform actions on the entities/objects. Therefore I would suggest that your solution is applied at the service layer (mid-tier).

A big part of the Spring Security architecture is dealing with authorisation decisions. It is worth taking your time to read that section of the documentation to ensure you understand the general architecture.

Broadly, Spring Security delegates pre-invocation access decisions to a AccessDecisionManager. The AccessDecisionManager typically consults a list of registered AccessionDecisionVoters who, as the name would suggest, "vote" on whether to allow the invocation to proceed based upon the current state of execution e.g. who is logged in, what data is the user requesting.

How a AccessDecisionVoter decides whether or not to give access is completely up to the implementation. So in theory you can do just about anything to decide whether or not to authorise a specific request.

Thankfully (and as you would expect) Spring provides some fairly sensible default implementations that let you achieve a lot of what you want out of the box. In particular I believe Method Security Expressions should let you achieve what you want (it will depend a little on how your services are implemented).

As per the documentation you can use Spring Security's @PreAuthorise annotation in combination with some expressions that look at the parameters of current method call or execution context. For example:

@PreAuthorise("#u == principal.id")
public List<Foo> loadFoos(@P("u")String userId);

In this example, the method invocation will only be allowed to proceed if the value of the userId parameter matches exactly the id of the currently authenticated user.

Your exact approach/expressions will depend on how your services are implemented, but hopefully this gives you a good starting point.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top