user2052618
user2052618

Reputation: 616

Spring Repository PreAuthorize gives 'failed to evaluate expression' error

i'm adding lots of bold because someone downgraded my question which is think is strange...

i went from this which worked which means things are configured correctly for @PreAuthorize...

@RestController
@RequestMapping('/people')
public PersonController extends BaseController {
   @PreAuthorize("#pesonId != principal.id")
   @RequestMapping(value="updatePerson", method={RequestMethod.POST}, produces = MediaType.APPLICATION_JSON_VALUE)
   public @ResponseBody SimpleResponseStatus updatePerson(@RequestParam(personId) final Long personId, @RequestParam(value) final String value, final HttpServerRequest request, final HttpServletResponse response)
   {
      Person p = personRepo.findById(personId);
      p.setValue(value);
      personRepo.save(p);
   }
}

and moved to this which doesn't work ... the @PreAuthorize in the Repository save()...

public interface PersonRepository extends JpaRepository<Person,Long> {

  @SuppressWarnings("unchecked")
  @Override
  @PreAuthorize("#p.id != principal.id")
  Person save(person p);

}

and now i get a "Failed to evaluate expression '#p.id != principal.id'

One difference between when it was working on the Controller was i did #personId and not #p.id so i don't know if the object vs primitive in the expression is the problem or if Controller vs Repository (where i do the evaluation) is the problem.

So i have a few questions...

  1. Do i have to do anything special to get the PreAuthorize working in the Repository?

  2. Nothing to do with Spring security but why was i forced to add the SuppressWarnings? i can see if i was returning List<Person> maybe but i thought that was strange.

  3. There is another instance where i will want to do an a PreAuthorize expression like "#p.group.id != 3" ... is there a limit to the levels that can be in an evaluation? i.e. level = obj.obj.obj.obj.value

Another interesting thing is that when i had it working with the Controller i didn't need curly braces "#{userId != 3}" but it worked with "#userId != 3" and i got that syntax from here.

Bottom line, i had it working in a Controller but without an object parameter and now i need it to work in a Repository and with an object parameter. And i've tried #person.id != 3 as well as #{person.id != 3} and neither work.

Upvotes: 1

Views: 7878

Answers (2)

user2052618
user2052618

Reputation: 616

i found the answer to my own question: here

which is basically for the Repository you have to add a parameter name via annotation since the debug isn't compiled into the interface.

it took me a long time to finally find the answer as it took trial and error of me trying different EL syntax and finally one syntax i chose gave me a different (and better) error message and from there i found the link above.

Anyway, whoever downgraded my question should have just posted the link i just did above instead of downgrading me. that is just mean, really.

public interface PersonRepository extends JpaRepository<Person,Long> {

  @SuppressWarnings("unchecked")
  @Override
  @PreAuthorize("#p.id != principal.id")
  Person save(@Param("p") person p);  //the @Param annotation is needed!

}

also, it is interesting how some places i see {} are needed and other places not. i did not need braces for this to work.

Upvotes: 5

Michele C.
Michele C.

Reputation: 101

you must first:
- enable global method security

in your spring security config just add

@EnableGlobalMethodSecurity(prePostEnabled=true)

the you can safely use @PreAuthorize and @PostAuthorize

  • correct SPEL syntax should be

    #{pesonId != principal.id}

but...before this you should ensure both parameter are present in SPringEvaluationContext.

I suggest to use Spring approach, which doesn't fit you question but gives you a different point of view of the problem.

Usage of expression bases access control
https://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html

ex: @PreAuthorize("hasRole('ADMIN')")

Spring security accept any valid Spel inside annotation.
Take a look here:
http://www.baeldung.com/spring-security-expressions-basic

Upvotes: 3

Related Questions