erotsppa
erotsppa

Reputation: 15031

How come @PreAuthorize wont be checked if called within the repository?

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

Answers (1)

Kartoch
Kartoch

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

Related Questions