Remove Advised Methods from Authorization Proxy Objects
Closes gh-15561
This commit is contained in:
parent
ecf6cace82
commit
fd05c5ad76
|
@ -171,6 +171,7 @@ public final class AuthorizationAdvisorProxyFactory
|
||||||
for (Advisor advisor : this.advisors) {
|
for (Advisor advisor : this.advisors) {
|
||||||
factory.addAdvisors(advisor);
|
factory.addAdvisors(advisor);
|
||||||
}
|
}
|
||||||
|
factory.setOpaque(true);
|
||||||
factory.setProxyTargetClass(!Modifier.isFinal(target.getClass().getModifiers()));
|
factory.setProxyTargetClass(!Modifier.isFinal(target.getClass().getModifiers()));
|
||||||
return factory.getProxy();
|
return factory.getProxy();
|
||||||
}
|
}
|
||||||
|
@ -357,6 +358,7 @@ public final class AuthorizationAdvisorProxyFactory
|
||||||
ProxyFactory factory = new ProxyFactory();
|
ProxyFactory factory = new ProxyFactory();
|
||||||
factory.setTargetClass(targetClass);
|
factory.setTargetClass(targetClass);
|
||||||
factory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass));
|
factory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass));
|
||||||
|
factory.setOpaque(true);
|
||||||
factory.setProxyTargetClass(!Modifier.isFinal(targetClass.getModifiers()));
|
factory.setProxyTargetClass(!Modifier.isFinal(targetClass.getModifiers()));
|
||||||
for (Advisor advisor : proxyFactory) {
|
for (Advisor advisor : proxyFactory) {
|
||||||
factory.addAdvisors(advisor);
|
factory.addAdvisors(advisor);
|
||||||
|
|
|
@ -34,6 +34,8 @@ import java.util.TreeSet;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@ -336,6 +338,18 @@ public class AuthorizationAdvisorProxyFactoryTests {
|
||||||
assertThat(factory.proxy(35)).isEqualTo(35);
|
assertThat(factory.proxy(35)).isEqualTo(35);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void serializeWhenAuthorizationProxyObjectThenOnlyIncludesProxiedProperties()
|
||||||
|
throws JsonProcessingException {
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(this.admin);
|
||||||
|
AuthorizationAdvisorProxyFactory factory = AuthorizationAdvisorProxyFactory.withDefaults();
|
||||||
|
User user = proxy(factory, this.alan);
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
String serialized = mapper.writeValueAsString(user);
|
||||||
|
Map<String, Object> properties = mapper.readValue(serialized, Map.class);
|
||||||
|
assertThat(properties).hasSize(3).containsKeys("id", "firstName", "lastName");
|
||||||
|
}
|
||||||
|
|
||||||
private Authentication authenticated(String user, String... authorities) {
|
private Authentication authenticated(String user, String... authorities) {
|
||||||
return TestAuthentication.authenticated(TestAuthentication.withUsername(user).authorities(authorities).build());
|
return TestAuthentication.authenticated(TestAuthentication.withUsername(user).authorities(authorities).build());
|
||||||
}
|
}
|
||||||
|
|
|
@ -2227,37 +2227,6 @@ class UserController {
|
||||||
----
|
----
|
||||||
======
|
======
|
||||||
|
|
||||||
If you are using Jackson, though, this may result in a serialization error like the following:
|
|
||||||
|
|
||||||
[source,bash]
|
|
||||||
====
|
|
||||||
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle
|
|
||||||
====
|
|
||||||
|
|
||||||
This is due to how Jackson works with CGLIB proxies.
|
|
||||||
To address this, add the following annotation to the top of the `User` class:
|
|
||||||
|
|
||||||
[tabs]
|
|
||||||
======
|
|
||||||
Java::
|
|
||||||
+
|
|
||||||
[source,java,role="primary"]
|
|
||||||
----
|
|
||||||
@JsonSerialize(as = User.class)
|
|
||||||
public class User {
|
|
||||||
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
Kotlin::
|
|
||||||
+
|
|
||||||
[source,kotlin,role="secondary"]
|
|
||||||
----
|
|
||||||
@JsonSerialize(`as` = User::class)
|
|
||||||
class User
|
|
||||||
----
|
|
||||||
======
|
|
||||||
|
|
||||||
Finally, you will need to publish a <<custom_advice, custom interceptor>> to catch the `AccessDeniedException` thrown for each field, which you can do like so:
|
Finally, you will need to publish a <<custom_advice, custom interceptor>> to catch the `AccessDeniedException` thrown for each field, which you can do like so:
|
||||||
|
|
||||||
[tabs]
|
[tabs]
|
||||||
|
|
Loading…
Reference in New Issue