I thought PostAuthorize decorated method should return an object having an attribute that is a part of authorization(e.g, 'username'). I put the annotation on getOrder() method show below. Why the annotation is not functioning?
@GetMapping("/read")
public String showOrderDetail(Model model, HttpServletRequest request,
Principal principal) {
String idStr = request.getParameter("id");
var corder = new Corder();
corder.setId(35);
if (idStr != null) {
Integer id = Integer.parseInt(idStr);
corder = this.getOrder(id, principal);
}
model.addAttribute("corder", corder);
return "orderDetails";
}
@PostAuthorize("hasRole('ADMIN') || " +
"authentication.name == returnObject.username")
private Corder getOrder(Integer id, Principal principal) {
Corder corder = repository.findById(id).orElseThrow();
User user = userRepository.findById(corder.getUserId()).get();
corder.setUsername(user.getUsername());
return corder;
}
Ok, so here is what is going on,
@GetMapping("/read")
public String showOrderDetail(Model model, HttpServletRequest request,
Principal principal) {
String idStr = request.getParameter("id");
var corder = new Corder();
corder.setId(35);
if (idStr != null) {
Integer id = Integer.parseInt(idStr);
corder = this.getOrder(id, principal); <------------------
}
model.addAttribute("corder", corder);
return "orderDetails";
}
@PostAuthorize("hasRole('ADMIN') || " +
"authentication.name == returnObject.username")
private Corder getOrder(Integer id, Principal principal) {
....
}
You invoke the method getOrder
internally from the same bean. This means that the call would not be able to take into consideration the annotation @PostAuthorize
when invoked internally, since the call will be made by the actual class that this method belongs to and not by the spring proxy class which will contain the actual code for the functionality of PostAuthorize
.
It should have worked if that method (getOrder
) was in some other class which was registered as a spring bean.
You can see here a very similar and known issue with @Transactional
.