浏览代码

Polish Saml2 Jackson Support

Issue gh-10905
Josh Cummings 3 年之前
父节点
当前提交
6c3d183a94

+ 1 - 1
core/src/test/java/org/springframework/security/jackson2/UnmodifiableMapDeserializerTests.java

@@ -47,7 +47,7 @@ class UnmodifiableMapDeserializerTests extends AbstractMixinTests {
 				Collections.unmodifiableMap(Collections.emptyMap()).getClass());
 
 		assertThat(map).isNotNull().isInstanceOf(Collections.unmodifiableMap(Collections.emptyMap()).getClass())
-				.containsAllEntriesOf(Map.of("Key", "Value"));
+				.containsAllEntriesOf(Collections.singletonMap("Key", "Value"));
 	}
 
 }

+ 0 - 66
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/jackson2/DefaultSaml2AuthenticatedPrincipalDeserializer.java

@@ -1,66 +0,0 @@
-/*
- * Copyright 2002-2022 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.jackson2;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
-
-/**
- * Custom deserializer for {@link DefaultSaml2AuthenticatedPrincipal}.
- *
- * @author Ulrich Grave
- * @since 5.7
- * @see DefaultSaml2AuthenticatedPrincipalMixin
- */
-class DefaultSaml2AuthenticatedPrincipalDeserializer extends JsonDeserializer<DefaultSaml2AuthenticatedPrincipal> {
-
-	private static final TypeReference<List<String>> SESSION_INDICES_LIST = new TypeReference<List<String>>() {
-	};
-
-	private static final TypeReference<Map<String, List<Object>>> ATTRIBUTES_MAP = new TypeReference<Map<String, List<Object>>>() {
-	};
-
-	@Override
-	public DefaultSaml2AuthenticatedPrincipal deserialize(JsonParser jp, DeserializationContext ctxt)
-			throws IOException {
-		ObjectMapper mapper = (ObjectMapper) jp.getCodec();
-		JsonNode jsonNode = mapper.readTree(jp);
-
-		String name = JsonNodeUtils.findStringValue(jsonNode, "name");
-		Map<String, List<Object>> attributes = JsonNodeUtils.findValue(jsonNode, "attributes", ATTRIBUTES_MAP, mapper);
-		List<String> sessionIndexes = JsonNodeUtils.findValue(jsonNode, "sessionIndexes", SESSION_INDICES_LIST, mapper);
-		String registrationId = JsonNodeUtils.findStringValue(jsonNode, "registrationId");
-
-		DefaultSaml2AuthenticatedPrincipal principal = new DefaultSaml2AuthenticatedPrincipal(name, attributes,
-				sessionIndexes);
-		if (registrationId != null) {
-			principal.setRelyingPartyRegistrationId(registrationId);
-		}
-		return principal;
-	}
-
-}

+ 15 - 2
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/jackson2/DefaultSaml2AuthenticatedPrincipalMixin.java

@@ -16,9 +16,13 @@
 
 package org.springframework.security.saml2.jackson2;
 
+import java.util.List;
+import java.util.Map;
+
 import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 
 import org.springframework.security.jackson2.SecurityJackson2Modules;
 import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
@@ -40,7 +44,16 @@ import org.springframework.security.saml2.provider.service.authentication.Defaul
  */
 @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
 @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
-@JsonDeserialize(using = DefaultSaml2AuthenticatedPrincipalDeserializer.class)
+@JsonIgnoreProperties(ignoreUnknown = true)
 class DefaultSaml2AuthenticatedPrincipalMixin {
 
+	@JsonProperty("registrationId")
+	String registrationId;
+
+	DefaultSaml2AuthenticatedPrincipalMixin(@JsonProperty("name") String name,
+			@JsonProperty("attributes") Map<String, List<Object>> attributes,
+			@JsonProperty("sessionIndexes") List<String> sessionIndexes) {
+
+	}
+
 }

+ 0 - 50
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/jackson2/JsonNodeUtils.java

@@ -1,50 +0,0 @@
-/*
- * Copyright 2002-2022 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.jackson2;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.MissingNode;
-
-final class JsonNodeUtils {
-
-	private JsonNodeUtils() {
-	}
-
-	static String findStringValue(JsonNode jsonNode, String fieldName) {
-		if (jsonNode == null) {
-			return null;
-		}
-		JsonNode value = jsonNode.findValue(fieldName);
-		return (value != null && value.isTextual()) ? value.asText() : null;
-	}
-
-	static <T> T findValue(JsonNode jsonNode, String fieldName, TypeReference<T> valueTypeReference,
-			ObjectMapper mapper) {
-		if (jsonNode == null) {
-			return null;
-		}
-		JsonNode value = jsonNode.findValue(fieldName);
-		return (value != null && value.isContainerNode()) ? mapper.convertValue(value, valueTypeReference) : null;
-	}
-
-	static JsonNode readJsonNode(JsonNode jsonNode, String field) {
-		return jsonNode.has(field) ? jsonNode.get(field) : MissingNode.getInstance();
-	}
-
-}

+ 0 - 71
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/jackson2/Saml2AuthenticationDeserializer.java

@@ -1,71 +0,0 @@
-/*
- * Copyright 2002-2022 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.jackson2;
-
-import java.io.IOException;
-import java.util.List;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import org.springframework.security.core.AuthenticatedPrincipal;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-
-/**
- * Custom deserializer for {@link Saml2Authentication}.
- *
- * @author Ulrich Grave
- * @since 5.7
- * @see Saml2AuthenticationMixin
- */
-class Saml2AuthenticationDeserializer extends JsonDeserializer<Saml2Authentication> {
-
-	private static final TypeReference<List<GrantedAuthority>> GRANTED_AUTHORITY_LIST = new TypeReference<List<GrantedAuthority>>() {
-	};
-
-	private static final TypeReference<Object> OBJECT = new TypeReference<Object>() {
-	};
-
-	@Override
-	public Saml2Authentication deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
-		ObjectMapper mapper = (ObjectMapper) jp.getCodec();
-		JsonNode jsonNode = mapper.readTree(jp);
-
-		boolean authenticated = JsonNodeUtils.readJsonNode(jsonNode, "authenticated").asBoolean();
-		JsonNode principalNode = JsonNodeUtils.readJsonNode(jsonNode, "principal");
-		AuthenticatedPrincipal principal = getPrincipal(mapper, principalNode);
-		String saml2Response = JsonNodeUtils.findStringValue(jsonNode, "saml2Response");
-		List<GrantedAuthority> authorities = JsonNodeUtils.findValue(jsonNode, "authorities", GRANTED_AUTHORITY_LIST,
-				mapper);
-		Object details = JsonNodeUtils.findValue(jsonNode, "details", OBJECT, mapper);
-
-		Saml2Authentication authentication = new Saml2Authentication(principal, saml2Response, authorities);
-		authentication.setAuthenticated(authenticated);
-		authentication.setDetails(details);
-		return authentication;
-	}
-
-	private AuthenticatedPrincipal getPrincipal(ObjectMapper mapper, JsonNode principalNode) throws IOException {
-		return mapper.readValue(principalNode.traverse(mapper), AuthenticatedPrincipal.class);
-	}
-
-}

+ 14 - 2
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/jackson2/Saml2AuthenticationMixin.java

@@ -16,10 +16,16 @@
 
 package org.springframework.security.saml2.jackson2;
 
+import java.util.Collection;
+
 import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 
+import org.springframework.security.core.AuthenticatedPrincipal;
+import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.jackson2.SecurityJackson2Modules;
 import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
 
@@ -40,7 +46,13 @@ import org.springframework.security.saml2.provider.service.authentication.Saml2A
 @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
 @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
 		isGetterVisibility = JsonAutoDetect.Visibility.NONE)
-@JsonDeserialize(using = Saml2AuthenticationDeserializer.class)
+@JsonIgnoreProperties(value = { "authenticated" }, ignoreUnknown = true)
 class Saml2AuthenticationMixin {
 
+	@JsonCreator
+	Saml2AuthenticationMixin(@JsonProperty("principal") AuthenticatedPrincipal principal,
+			@JsonProperty("saml2Response") String saml2Response,
+			@JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities) {
+	}
+
 }

+ 0 - 1
saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/jackson2/TestSaml2JsonPayloads.java

@@ -204,7 +204,6 @@ final class TestSaml2JsonPayloads {
 			+ "		\"credentialsNonExpired\": true,"
 			+ "		\"enabled\": true"
 			+ "	},"
-			+ "	\"authenticated\": true,"
 			+ "	\"principal\": " + DEFAULT_AUTHENTICATED_PRINCIPAL_JSON + ","
 			+ "	\"saml2Response\": \"" + SAML_RESPONSE + "\""
 			+ "}";