浏览代码

Remove Advised Methods from Authorization Proxy Objects

Closes gh-15561
DingHao 1 年之前
父节点
当前提交
fd05c5ad76

+ 2 - 0
core/src/main/java/org/springframework/security/authorization/method/AuthorizationAdvisorProxyFactory.java

@@ -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);

+ 14 - 0
core/src/test/java/org/springframework/security/authorization/AuthorizationAdvisorProxyFactoryTests.java

@@ -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());
 	}
 	}

+ 0 - 31
docs/modules/ROOT/pages/servlet/authorization/method-security.adoc

@@ -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]