Răsfoiți Sursa

Add WebFlux support for spring security web jackson module.

Fixes: gh-6303
finke-ba 6 ani în urmă
părinte
comite
b838f7c7b7

+ 3 - 1
core/src/main/java/org/springframework/security/jackson2/SecurityJackson2Modules.java

@@ -58,6 +58,7 @@ import java.util.Set;
  *     mapper.registerModule(new CasJackson2Module());
  *     mapper.registerModule(new WebJackson2Module());
  *     mapper.registerModule(new WebServletJackson2Module());
+ *     mapper.registerModule(new WebServerJackson2Module());
  * </pre>
  *
  * @author Jitendra Singh.
@@ -69,7 +70,8 @@ public final class SecurityJackson2Modules {
 	private static final List<String> securityJackson2ModuleClasses = Arrays.asList(
 			"org.springframework.security.jackson2.CoreJackson2Module",
 			"org.springframework.security.cas.jackson2.CasJackson2Module",
-			"org.springframework.security.web.jackson2.WebJackson2Module"
+			"org.springframework.security.web.jackson2.WebJackson2Module",
+			"org.springframework.security.web.server.jackson2.WebServerJackson2Module"
 	);
 	private static final String webServletJackson2ModuleClass =
 			"org.springframework.security.web.jackson2.WebServletJackson2Module";

+ 53 - 0
web/src/main/java/org/springframework/security/web/server/jackson2/DefaultCsrfServerTokenMixin.java

@@ -0,0 +1,53 @@
+/*
+ * Copyright 2015-2018 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
+ *
+ *      http://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.web.server.jackson2;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+/**
+ * Jackson mixin class to serialize/deserialize {@link org.springframework.security.web.server.csrf.DefaultCsrfToken}
+ * serialization support.
+ *
+ * <pre>
+ * 		ObjectMapper mapper = new ObjectMapper();
+ * 		mapper.registerModule(new WebServerJackson2Module());
+ * </pre>
+ *
+ * @author Boris Finkelshteyn
+ * @see WebServerJackson2Module
+ * @since 5.1
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
+@JsonIgnoreProperties(ignoreUnknown = true)
+class DefaultCsrfServerTokenMixin {
+
+	/**
+	 * JsonCreator constructor needed by Jackson to create {@link org.springframework.security.web.server.csrf.DefaultCsrfToken}
+	 * object.
+	 *
+	 * @param headerName    the name of the header
+	 * @param parameterName the parameter name
+	 * @param token         the CSRF token value
+	 */
+	@JsonCreator
+	public DefaultCsrfServerTokenMixin(@JsonProperty("headerName") String headerName,
+										@JsonProperty("parameterName") String parameterName, @JsonProperty("token") String token) {
+	}
+}

+ 51 - 0
web/src/main/java/org/springframework/security/web/server/jackson2/WebServerJackson2Module.java

@@ -0,0 +1,51 @@
+/*
+ * Copyright 2015-2018 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
+ *
+ *      http://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.web.server.jackson2;
+
+import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import org.springframework.security.jackson2.SecurityJackson2Modules;
+import org.springframework.security.web.server.csrf.DefaultCsrfToken;
+
+/**
+ * Jackson module for spring-security-web-flux. This module register {@link DefaultCsrfServerTokenMixin}
+ * If no default typing enabled by default then it'll enable it because typing info is needed to
+ * properly serialize/deserialize objects.
+ * In order to use this module just add this module into your ObjectMapper configuration.
+ *
+ * <pre>
+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.registerModule(new WebServerJackson2Module());
+ * </pre>
+ * <b>Note: use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get list of all security modules.</b>
+ *
+ * @author Boris Finkelshteyn
+ * @see SecurityJackson2Modules
+ * @since 5.1
+ */
+public class WebServerJackson2Module extends SimpleModule {
+
+	public WebServerJackson2Module() {
+		super(WebServerJackson2Module.class.getName(), new Version(1, 0, 0, null, null, null));
+	}
+
+	@Override
+	public void setupModule(SetupContext context) {
+		SecurityJackson2Modules.enableDefaultTyping(context.getOwner());
+		context.setMixInAnnotations(DefaultCsrfToken.class, DefaultCsrfServerTokenMixin.class);
+	}
+}

+ 73 - 0
web/src/test/java/org/springframework/security/web/server/jackson2/DefaultCsrfServerTokenMixinTests.java

@@ -0,0 +1,73 @@
+/*
+ * Copyright 2015-2016 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
+ *
+ *      http://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.web.server.jackson2;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import org.json.JSONException;
+import org.junit.Test;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.springframework.security.web.jackson2.AbstractMixinTests;
+import org.springframework.security.web.server.csrf.DefaultCsrfToken;
+
+import java.io.IOException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Boris Finkelshteyn
+ * @since 5.1
+ */
+public class DefaultCsrfServerTokenMixinTests extends AbstractMixinTests {
+
+	// @formatter:off
+	private static final String CSRF_JSON = "{"
+			+ "\"@class\": \"org.springframework.security.web.server.csrf.DefaultCsrfToken\", "
+			+ "\"headerName\": \"csrf-header\", "
+			+ "\"parameterName\": \"_csrf\", "
+			+ "\"token\": \"1\""
+			+ "}";
+	// @formatter:on
+
+	@Test
+	public void defaultCsrfTokenSerializedTest() throws JsonProcessingException, JSONException {
+		DefaultCsrfToken token = new DefaultCsrfToken("csrf-header", "_csrf", "1");
+		String serializedJson = mapper.writeValueAsString(token);
+		JSONAssert.assertEquals(CSRF_JSON, serializedJson, true);
+	}
+
+	@Test
+	public void defaultCsrfTokenDeserializeTest() throws IOException {
+		DefaultCsrfToken token = mapper.readValue(CSRF_JSON, DefaultCsrfToken.class);
+		assertThat(token).isNotNull();
+		assertThat(token.getHeaderName()).isEqualTo("csrf-header");
+		assertThat(token.getParameterName()).isEqualTo("_csrf");
+		assertThat(token.getToken()).isEqualTo("1");
+	}
+
+	@Test(expected = JsonMappingException.class)
+	public void defaultCsrfTokenDeserializeWithoutClassTest() throws IOException {
+		String tokenJson = "{\"headerName\": \"csrf-header\", \"parameterName\": \"_csrf\", \"token\": \"1\"}";
+		mapper.readValue(tokenJson, DefaultCsrfToken.class);
+	}
+
+	@Test(expected = JsonMappingException.class)
+	public void defaultCsrfTokenDeserializeNullValuesTest() throws IOException {
+		String tokenJson = "{\"@class\": \"org.springframework.security.web.server.csrf.DefaultCsrfToken\", \"headerName\": \"\", \"parameterName\": null, \"token\": \"1\"}";
+		mapper.readValue(tokenJson, DefaultCsrfToken.class);
+	}
+}