Reputation: 15031
I was looking ways to bypass @PreAuthorize if I'm calling the code myself and to be surprise the following works:
@RepositoryRestResource(excerptProjection = UserSummaryProjection.class)
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
/**
* Saves entity without security checks.
*/
@RestResource(exported = false)
default User saveInternal(User entity) {
return save(entity);
}
@PreAuthorize("@userValidator.hasWritePermission(#user)")
@Override
User save(User user);
}
And then somewhere in my controller code..
public @ResponseBody
ResponseEntity<?> controllerMethod(@RequestBody param) {
userRepository.saveInternal(user); //does not PreAuthorize check
userRepository.save(user); //does DO PreAuthorize check
}
This is working the way I want it do, but why does it work? Because wouldn't saveInternal just end up calling save() anyways and therefore requiring a check?
Upvotes: 1
Views: 186
Reputation: 7779
Spring security constructs proxies for security check.
In your case, a proxy is generated during startup which implements the interface UserRepository
. The bean B implementing the interface is theoretically injected via @Resource
in a bean A. But in fact, this is the reference of the proxy which is injected. So when Bean A calls a method of Bean B, it calls the proxy.
A --> proxy --> B
But if a method of B (saveInternal
) calls another method of B (save
), it does not get pass by the proxy again, it directly calls the method.
Upvotes: 1