4

We have an application where users can be created by an administrator and assigned roles to a particular type of entity.

For example, if the entity is called Student, the users of the application have different levels of privileges such as:

  • VIEWER - View Student details
  • EDITOR - Edit Student details
  • EXPORTER - Export Student details

The URIs for performing the above actions look like:

  • GET - /content/{classId}/{studentId}/view
  • PUT - /content/{classId}/{studentId}
  • GET - /content/{classId}/{studentId}/export
  • POST - /content/{classId}/{studentId}/export

Note that the URIs are of a dynamic nature. Also, a given user User A can be assigned VIEWER role for Class 1 and EXPORTER for Class 2.

In my spring-security configuration, I have only two authorities defined - ADMINISTRATOR and USER.

  • ADMINISTRATOR - can access everything
  • USER - can access everything except the /admin/* URI.

The roles VIEWER, EDITOR, EXPORTER are not spring-security roles. Now I have run into a problem while restricting users from accessing resources to which they don't have the rights.

Also, if a user doesn't have the EXPORTER right, he shouldn't even see the Export button (placed somewhere on the application). Perhaps I can do this using the spring's security taglib. But that's another issue altogether.

I can make them spring-security aware but the question is where do I put my logic of reading {studentId} (@PathVariable) and match it against the current logged in user to check if he has the access to it.

I even thought of the idea of creating a filter / HandlerInterceptor that listens on /content/*. But I will have to do ugly things like parsing the URI, extracting the second path parameter myself and then checking against the database.

Is there a more elegant, spring-security way of doing this?

Any thoughts welcome.

adarshr
  • 61,315
  • 23
  • 138
  • 167

1 Answers1

3

you can provide spring security your own implementation of SecurityExpressionHandler. Just extend DefaultWebSecurityExpressionHandler and override the createSecurityExpressionRoot. By default this method returns a instance of WebSecurityExpressionRoot. Your implementation could just extend this class and add additional methods, which you would use in your spring security configuration.

here is how you provide your own implementation of SecurityExpressionHandler. The code comes from the spring security documentation:

<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.DefaultMethodSecurityExpressionHandler">
    <property name="permissionEvaluator" ref="myPermissionEvaluator"/>
</bean>

Does the answer provide enough information or do you need further assistance?

Yevgeniy
  • 2,614
  • 1
  • 19
  • 26
  • Thanks, I will explore a bit and come back to you. – adarshr Dec 07 '12 at 16:43
  • you are welcome. by the way, here is another question+answer with a similar topic:http://stackoverflow.com/questions/6632982/how-to-create-custom-methods-for-use-in-spring-security-expression-language-anno – Yevgeniy Dec 07 '12 at 16:45
  • I just had to implement a `PermissionEvaluator` and use `@PreAuthorize("hasPermission(#studentId, 'EDITOR')` and so on over my `@RequestMapping`s. However, since I have a dedicated controller for each URI root, I just had to define the `@PreAuthorize` on the class level. Thanks a lot. – adarshr Dec 11 '12 at 13:08