Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Value-Type Ignore Support #14780

Merged
merged 4 commits into from
Mar 22, 2024
Merged

Conversation

jzheaux
Copy link
Contributor

@jzheaux jzheaux commented Mar 20, 2024

This PR makes using @AuthorizeReturnObject practical on a more diverse set of classes and interfaces, including Spring Data interfaces.

A typical Spring Data interface begins like this:

public interface UserRepository extends CrudRepository<User, UUID> {
}

and because CrudRepository has methods that return primitive types like int count(), an application cannot use @AuthorizeReturnObject at the class level.

This is a reasonable default since the semantics around Spring Security method security annotations are that placing it at the class level is functionally equivalent to placing it on the method level. Since it would be an error to use @AuthorizeReturnObject on a method that returns an int, we want to error by default.

With this PR, an application can relax that behavior by doing:

@Bean 
Customizer<AuthorizationAdvisorProxyFactory> skipValueTypes() {
    return (factory) -> factory.setTargetVisitor(TargetVisitor.defaultsSkipValueTypes());
}

It incidentally introduces an inner interface AuthorizationAdvisorProxyFactory.TargetVisitor to simplify any kind of proxy customization of the target object.

The reason I like this approach is that it gives folks more power to customize how a given type is handled. The alternative is to not use @EnableMethodSecurity so that they can publish their own AuthorizationProxyFactory or possibly add a bean factory post-processor to inject their own authorization proxy factory implementation.

Here are some simple examples other than ignoring a type are to use different ProxyFactory settings or to programmatically visit an object:

TargetVisitor visitor = (proxyFactory, target) -> {
    if (target instanceof Function function) { // support a novel container type
        return (input) -> proxyFactory.proxy(function.apply(input));
    }
    if (target instanceof Map map) { // customize a supported container type
        Map proxies = new LinkedHashMap<>(map.size());
        for (Map.Entry entry : map.entrySet()) {
            proxies.put(proxyFactory.proxy(entry.getKey()), proxyFactory.proxy(entry.getValue()));
        }
        return Collections.unmodifiableMap(proxies);
    }
    if (target instanceof MyObject object) { // proxying nested target
        object.setX(proxyFactory.visit(object.getX());
        object.setY(proxyFactory.visit(object.getY());
        return object;
    }
    if (target class has some custom annotation) { // perform proxying differently
        ProxyFactory custom = ...
        custom.setAopProxyFactory(new MyAopProxyFactory())
        for (AuthorizationAdvisor advisor : proxyFactory) {
            custom.addAdvisor(advisor);
        }
        return custom.getProxy();
    }
    return null;
}

// ...

@Bean 
Customizer<AuthorizationAdvisorProxyFactory> customProxying() {
    return (f) -> f.setTargetVisitor(TargetVisitor.of(visitor, TargetVisitor.defaultsSkipValueTypes()));
}

Issue gh-14597

@jzheaux jzheaux force-pushed the gh-14597-delegate branch 4 times, most recently from 7db844d to 776c8d6 Compare March 21, 2024 22:54
@jzheaux jzheaux self-assigned this Mar 21, 2024
@jzheaux jzheaux force-pushed the gh-14597-delegate branch 2 times, most recently from 3052bc2 to 6c10822 Compare March 21, 2024 23:34
@jzheaux jzheaux marked this pull request as ready for review March 21, 2024 23:46
@jzheaux jzheaux force-pushed the gh-14597-delegate branch from 6c10822 to 0fed00d Compare March 22, 2024 16:09
@jzheaux jzheaux force-pushed the gh-14597-delegate branch from 0fed00d to bc8bfc8 Compare March 22, 2024 16:37
@jzheaux jzheaux added in: core An issue in spring-security-core type: enhancement A general enhancement labels Mar 22, 2024
@jzheaux jzheaux added this to the 6.3.0-RC1 milestone Mar 22, 2024
@jzheaux jzheaux merged commit e1c5dc0 into spring-projects:main Mar 22, 2024
3 checks passed
@jzheaux jzheaux deleted the gh-14597-delegate branch March 22, 2024 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core An issue in spring-security-core type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant