0

We currently have different roles in our environments, for example in development we have roles called USR and ADM, while in production they use full names for example USER, ADMIN and ADMINISTRATOR.

My idea to resolve this problem is to use a property file and a placeholder for the rolenames, for example, this is my properties file:

role.user='USER'
role.admin='ADMIN', 'ADMINISTRATOR'

In my AppConfig I added the following annotation on top of the class:

@PropertySource("classpath:roles.properties")
public class AppConfig {

}

And in my service I'm now using:

@PreAuthorize("hasAnyRole(${role.admin})")
public Item deleteItem(int id) {

}

However, this results in the following exception:

Caused by: org.springframework.expression.spel.SpelParseException: EL1043E:(pos 12): Unexpected token.  Expected 'rparen())' but was 'lcurly({)'

Because it says it's not expexting the curly brace, I also tried the following: @PreAuthorize("hasAnyRole(role.admin)") which results in:

Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 11): Property or field 'role' cannot be found on object of type 'org.springframework.security.access.expression.method.MethodSecurityExpressionRoot' - maybe not public?

At least the expression itself looks valid now, but it seems it's not looking at the properties file no, but at a property of a specific class.

Does anyone have an idea to solve this? Or is there another/better solution of resolving environment-specific roles?

g00glen00b
  • 41,995
  • 13
  • 95
  • 133
  • I would translate role names right when they are read. Or alternatively you can use role hierarchy. – Pavel Horal Aug 26 '14 at 08:08
  • Btw. `${}` is format for property placeholder. For SpEL you might want to try `environment['role.admin']`. – Pavel Horal Aug 26 '14 at 08:12
  • The `environment['role.admin]` isn't working either, it gives the same exception (it's looking for `environment` in `MethodSecurityExpressionRoot`. I'll try the other options later (take some more time to implement). – g00glen00b Aug 26 '14 at 08:30

1 Answers1

2

The Spring EL used in @PreAuthorize does only have:

  • Access to methods and properties of SecurityExpressionRoot.

  • Access method arguments (requires compilation with debug info or custom ParameterNameDiscoverer):

See this answer https://stackoverflow.com/a/3786581/883859

You can get access to other beans via @ so

 public interface RoleNameGetter {
    String getSuperUserRole();
    ...
 }

And

 @Configuration
 @PropertySource("classpath:xyz.properties")
 @EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
 public class Configuration {
    @Autowired
    protected Environment env;

    @Bean
    RoleNameGetter roleNameGetter() {
      return new RoleNameGetter() {
        @Override
        public String getSuperUserRole() {
            return env.getProperty("superuser_role_name");
        }
    };
}

Allows for access to role names from the property file in the Spring EL used in @PreAuthorize, like this:

  @PreAuthorize("hasAnyAuthority(@roleNameGetter.getSuperUserRole(),@roleNameGetter.getNormalUserRole())")
  public void end() {...}
Community
  • 1
  • 1
cmadsen
  • 354
  • 4
  • 19