Reputation: 616
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...
Do i have to do anything special to get the PreAuthorize working in the Repository?
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.
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
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
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