4

I have the following interface method on which I am applying @PreAuthorize :

@PreAuthorize("doSomething(#user.id)")
void something(User user, List<User> accessList);

where User is a Hibernate entity object. It gives me an error :

org.springframework.expression.spel.SpelEvaluationException: EL1007E:(pos 13): Field or property 'id' cannot be found on null at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:204)

There is no way that the user parameter is null, as if I remove the annotation, and inspect the value of user in the method that implements this interface method, there is a valid User object present there. Additionally, just before calling this method, I have made sure that the user object is correctly constructed.

I really can't figure out why would the user field be considered null by the SPEL parser

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Daud
  • 7,429
  • 18
  • 68
  • 115

4 Answers4

2

You can check with the debugger what's going on in MethodSecurityEvaluationContext, inside Object lookupVariable(String name) method:

    @Override
    public Object lookupVariable(String name) {
    Object variable = super.lookupVariable(name);

    if (variable != null) {
        return variable;
    }

    if (!argumentsAdded) {
        addArgumentsAsVariables();
        argumentsAdded = true;
    }

and so you can see what's really going on in the addArgumentsAsVariables() method as the convertion of method arguments to SPEL variables is implemented very clearly in Spring.

Boris Treukhov
  • 17,493
  • 9
  • 70
  • 91
  • 1
    Thanks for that.. As it turned out, the variable name in my method argument in the interface declaration was different than the name in my actual implementation of the method... Spring was looking for the latter name – Daud May 27 '12 at 07:42
1

Spring Security has a better answer for this problem now:

http://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#access-control-using-preauthorize-and-postauthorize

Basically, you can use the @P annotation or @Param annotation if you are using < JDK 8.

Shawn Sherwood
  • 1,968
  • 2
  • 19
  • 30
0

You can check LazyParamAwareEvaluationContext,inside loadArgsAsVariables() method, version 3.1.0.

The same key for different Entity, because of implementing interface.

j0k
  • 22,600
  • 28
  • 79
  • 90
0

I need to add something to this as the title indicates that we cannot access hibernate properties.

There are two editions of hasPermission, the loaded object and the serialized object. Here is some code from a test case:

@PreAuthorize("isAuthenticated() and hasPermission(#organization, 'edit')")
public long protectedMethod(Organization organization)
{
    return organization.getId();
}

And for the latter here we see that we can infact access the id proprty of the organization (which is a hibernate entity):

@PreAuthorize("isAuthenticated() and hasPermission(#organization.getId(), 'organization', 'edit')")
public long protectedMethodSerializableEdtion(Organization organization)
{
    return organization.getId();
}
CodeTower
  • 6,293
  • 5
  • 30
  • 54