springspring-security

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.


Solution

  • 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.