>() {
+ });
+ JsonNode password = readJsonNode(jsonNode, "password");
+ User result = new User(readJsonNode(jsonNode, "username").asText(),
+ password.asText(""), readJsonNode(jsonNode, "enabled").asBoolean(),
+ readJsonNode(jsonNode, "accountNonExpired").asBoolean(),
+ readJsonNode(jsonNode, "credentialsNonExpired").asBoolean(),
+ readJsonNode(jsonNode, "accountNonLocked").asBoolean(), authorities);
+
+ if (password.asText(null) == null) {
+ result.eraseCredentials();
+ }
+ return result;
+ }
+
+ private JsonNode readJsonNode(JsonNode jsonNode, String field) {
+ return jsonNode.has(field) ? jsonNode.get(field) : MissingNode.getInstance();
+ }
+}
diff --git a/samples/httpsession-redis-json/src/main/java/org/springframework/security/jackson2/UserMixin.java b/samples/httpsession-redis-json/src/main/java/org/springframework/security/jackson2/UserMixin.java
new file mode 100644
index 00000000..6d4cda3c
--- /dev/null
+++ b/samples/httpsession-redis-json/src/main/java/org/springframework/security/jackson2/UserMixin.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014-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.jackson2;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+/**
+ * This mixin class helps in serialize/deserialize
+ * {@link org.springframework.security.core.userdetails.User}. This class also register a
+ * custom deserializer {@link UserDeserializer} to deserialize User object successfully.
+ * In order to use this mixin you need to register two more mixin classes in your
+ * ObjectMapper configuration.
+ *
+ * - {@link SimpleGrantedAuthorityMixin}
+ * - {@link UnmodifiableSetMixin}
+ *
+ *
+ * ObjectMapper mapper = new ObjectMapper();
+ * mapper.registerModule(new CoreJackson2Module());
+ *
+ *
+ * @author Jitendra Singh
+ * @see UserDeserializer
+ * @see CoreJackson2Module
+ * @see SecurityJacksonModules
+ * @since 4.2
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
+@JsonDeserialize(using = UserDeserializer.class)
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE)
+@JsonIgnoreProperties(ignoreUnknown = true)
+abstract class UserMixin {
+}
diff --git a/samples/httpsession-redis-json/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java b/samples/httpsession-redis-json/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java
new file mode 100644
index 00000000..bf5bc5a2
--- /dev/null
+++ b/samples/httpsession-redis-json/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2014-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.jackson2;
+
+import java.io.IOException;
+import java.util.List;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+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 com.fasterxml.jackson.databind.node.MissingNode;
+
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+
+/**
+ * Custom deserializer for {@link UsernamePasswordAuthenticationToken}. At the time of
+ * deserialization it will invoke suitable constructor depending on the value of
+ * authenticated property. It will ensure that the token's state must not change.
+ *
+ * This deserializer is already registered with
+ * {@link UsernamePasswordAuthenticationTokenMixin} but you can also registered it with
+ * your own mixin class.
+ *
+ * @author Jitendra Singh
+ * @see UsernamePasswordAuthenticationTokenMixin
+ */
+class UsernamePasswordAuthenticationTokenDeserializer
+ extends JsonDeserializer {
+
+ /**
+ * This method construct {@link UsernamePasswordAuthenticationToken} object from
+ * serialized json.
+ * @param jp the JsonParser
+ * @param ctxt the DeserializationContext
+ * @return the user
+ * @throws IOException if a exception during IO occurs
+ * @throws JsonProcessingException if an error during JSON processing occurs
+ */
+ @Override
+ public UsernamePasswordAuthenticationToken deserialize(JsonParser jp,
+ DeserializationContext ctxt) throws IOException, JsonProcessingException {
+ UsernamePasswordAuthenticationToken token = null;
+ ObjectMapper mapper = (ObjectMapper) jp.getCodec();
+ JsonNode jsonNode = mapper.readTree(jp);
+ Boolean authenticated = readJsonNode(jsonNode, "authenticated").asBoolean();
+ JsonNode principalNode = readJsonNode(jsonNode, "principal");
+ Object principal = null;
+ if (principalNode.isObject()) {
+ principal = mapper.readValue(principalNode.toString(),
+ new TypeReference() {
+ });
+ }
+ else {
+ principal = principalNode.asText();
+ }
+ Object credentials = readJsonNode(jsonNode, "credentials").asText();
+ List authorities = mapper.readValue(
+ readJsonNode(jsonNode, "authorities").toString(),
+ new TypeReference>() {
+ });
+ if (authenticated) {
+ token = new UsernamePasswordAuthenticationToken(principal, credentials,
+ authorities);
+ }
+ else {
+ token = new UsernamePasswordAuthenticationToken(principal, credentials);
+ }
+ token.setDetails(readJsonNode(jsonNode, "details"));
+ return token;
+ }
+
+ private JsonNode readJsonNode(JsonNode jsonNode, String field) {
+ return jsonNode.has(field) ? jsonNode.get(field) : MissingNode.getInstance();
+ }
+}
diff --git a/samples/httpsession-redis-json/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java b/samples/httpsession-redis-json/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java
new file mode 100644
index 00000000..b323c1a0
--- /dev/null
+++ b/samples/httpsession-redis-json/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2014-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.jackson2;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+/**
+ * This mixin class is used to serialize / deserialize
+ * {@link org.springframework.security.authentication.UsernamePasswordAuthenticationToken}
+ * . This class register a custom deserializer
+ * {@link UsernamePasswordAuthenticationTokenDeserializer}.
+ *
+ * In order to use this mixin you'll need to add 3 more mixin classes.
+ *
+ * - {@link UnmodifiableSetMixin}
+ * - {@link SimpleGrantedAuthorityMixin}
+ * - {@link UserMixin}
+ *
+ *
+ *
+ * ObjectMapper mapper = new ObjectMapper();
+ * mapper.registerModule(new CoreJackson2Module());
+ *
+ * @author Jitendra Singh
+ * @see CoreJackson2Module
+ * @see SecurityJacksonModules
+ * @since 4.2
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE)
+@JsonDeserialize(using = UsernamePasswordAuthenticationTokenDeserializer.class)
+abstract class UsernamePasswordAuthenticationTokenMixin {
+}
diff --git a/samples/httpsession-redis-json/src/main/java/org/springframework/security/jackson2/package-info.java b/samples/httpsession-redis-json/src/main/java/org/springframework/security/jackson2/package-info.java
new file mode 100644
index 00000000..0c2a3a9f
--- /dev/null
+++ b/samples/httpsession-redis-json/src/main/java/org/springframework/security/jackson2/package-info.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2014-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.
+ */
+
+/**
+ * Mix-in classes to add Jackson serialization support.
+ *
+ * @author Jitendra Singh
+ * @since 4.2
+ */
+package org.springframework.security.jackson2;
+
+/**
+ * Package contains Jackson mixin classes.
+ */
diff --git a/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java
new file mode 100644
index 00000000..ed31fe4f
--- /dev/null
+++ b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2014-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.jackson2;
+
+import java.io.IOException;
+
+import javax.servlet.http.Cookie;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+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 com.fasterxml.jackson.databind.node.MissingNode;
+import com.fasterxml.jackson.databind.node.NullNode;
+
+/**
+ * Jackson deserializer for {@link Cookie}. This is needed because in most cases we don't
+ * set {@link Cookie#getDomain()} property. So when jackson deserialize that json
+ * {@link Cookie#setDomain(String)} throws {@link NullPointerException}. This is
+ * registered with {@link CookieMixin} but you can also use it with your own mixin.
+ *
+ * @author Jitendra Singh
+ * @see CookieMixin
+ */
+class CookieDeserializer extends JsonDeserializer {
+
+ @Override
+ public Cookie deserialize(JsonParser jp, DeserializationContext ctxt)
+ throws IOException, JsonProcessingException {
+ ObjectMapper mapper = (ObjectMapper) jp.getCodec();
+ JsonNode jsonNode = mapper.readTree(jp);
+ Cookie cookie = new Cookie(readJsonNode(jsonNode, "name").asText(),
+ readJsonNode(jsonNode, "value").asText());
+ cookie.setComment(readJsonNode(jsonNode, "comment").asText());
+ cookie.setDomain(readJsonNode(jsonNode, "domain").asText());
+ cookie.setMaxAge(readJsonNode(jsonNode, "maxAge").asInt(-1));
+ cookie.setSecure(readJsonNode(jsonNode, "secure").asBoolean());
+ cookie.setVersion(readJsonNode(jsonNode, "version").asInt());
+ cookie.setPath(readJsonNode(jsonNode, "path").asText());
+ cookie.setHttpOnly(readJsonNode(jsonNode, "httpOnly").asBoolean());
+ return cookie;
+ }
+
+ private JsonNode readJsonNode(JsonNode jsonNode, String field) {
+ return jsonNode.has(field) && !(jsonNode.get(field) instanceof NullNode)
+ ? jsonNode.get(field) : MissingNode.getInstance();
+ }
+}
diff --git a/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java
new file mode 100644
index 00000000..2ffb20f6
--- /dev/null
+++ b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014-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.jackson2;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+/**
+ * Mixin class to serialize/deserialize {@link javax.servlet.http.Cookie}
+ *
+ *
+ * ObjectMapper mapper = new ObjectMapper();
+ * mapper.registerModule(new WebJackson2Module());
+ *
+ *
+ * @author Jitendra Singh
+ * @see WebJackson2Module
+ * @see org.springframework.security.jackson2.SecurityJacksonModules
+ * @since 4.2
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
+@JsonDeserialize(using = CookieDeserializer.class)
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE)
+abstract class CookieMixin {
+}
diff --git a/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java
new file mode 100644
index 00000000..7fb64292
--- /dev/null
+++ b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2014-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.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.csrf.DefaultCsrfToken} serialization support.
+ *
+ *
+ * ObjectMapper mapper = new ObjectMapper();
+ * mapper.registerModule(new WebJackson2Module());
+ *
+ *
+ * @author Jitendra Singh
+ * @see WebJackson2Module
+ * @see org.springframework.security.jackson2.SecurityJacksonModules
+ * @since 4.2
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
+@JsonIgnoreProperties(ignoreUnknown = true)
+class DefaultCsrfTokenMixin {
+
+ /**
+ * JsonCreator constructor needed by Jackson to create
+ * {@link org.springframework.security.web.csrf.DefaultCsrfToken} object.
+ *
+ * @param headerName the name of the header
+ * @param parameterName the parameter name
+ * @param token the CSRF token value
+ */
+ @JsonCreator
+ DefaultCsrfTokenMixin(@JsonProperty("headerName") String headerName,
+ @JsonProperty("parameterName") String parameterName,
+ @JsonProperty("token") String token) {
+ }
+}
diff --git a/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestBuilder.java b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestBuilder.java
new file mode 100644
index 00000000..9c0966e1
--- /dev/null
+++ b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestBuilder.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2014-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.jackson2;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import org.springframework.security.web.savedrequest.DefaultSavedRequest;
+
+/**
+ * Spring Security 4.2 will support saved request.
+ *
+ * @author Rob Winch
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class DefaultSavedRequestBuilder {
+
+ public DefaultSavedRequest build() {
+ return null;
+ }
+}
diff --git a/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java
new file mode 100644
index 00000000..16db2f96
--- /dev/null
+++ b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014-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.jackson2;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+import org.springframework.security.web.savedrequest.DefaultSavedRequest;
+
+/**
+ * Jackson mixin class to serialize/deserialize {@link DefaultSavedRequest}. This mixin
+ * use {@link org.springframework.security.web.savedrequest.DefaultSavedRequest.Builder}
+ * to deserialized json.In order to use this mixin class you also need to register
+ * {@link CookieMixin}.
+ *
+ *
+ * ObjectMapper mapper = new ObjectMapper();
+ * mapper.registerModule(new WebJackson2Module());
+ *
+ *
+ * @author Jitendra Singh
+ * @see WebJackson2Module
+ * @see org.springframework.security.jackson2.SecurityJacksonModules
+ * @since 4.2
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
+@JsonDeserialize(builder = DefaultSavedRequestBuilder.class)
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
+abstract class DefaultSavedRequestMixin {
+}
diff --git a/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/SavedCookieMixin.java b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/SavedCookieMixin.java
new file mode 100644
index 00000000..f0cdd7f5
--- /dev/null
+++ b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/SavedCookieMixin.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2014-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.jackson2;
+
+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;
+
+/**
+ * Jackson mixin class to serialize/deserialize
+ * {@link org.springframework.security.web.savedrequest.SavedCookie} serialization
+ * support.
+ *
+ *
+ * ObjectMapper mapper = new ObjectMapper();
+ * mapper.registerModule(new WebJackson2Module());
+ *
+ *
+ * @author Jitendra Singh.
+ * @see WebJackson2Module
+ * @see org.springframework.security.jackson2.SecurityJacksonModules
+ * @since 4.2
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
+@JsonIgnoreProperties(ignoreUnknown = true)
+abstract class SavedCookieMixin {
+
+ @JsonCreator
+ SavedCookieMixin(@JsonProperty("name") String name,
+ @JsonProperty("value") String value, @JsonProperty("comment") String comment,
+ @JsonProperty("domain") String domain, @JsonProperty("maxAge") int maxAge,
+ @JsonProperty("path") String path, @JsonProperty("secure") boolean secure,
+ @JsonProperty("version") int version) {
+
+ }
+}
diff --git a/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java
new file mode 100644
index 00000000..e65b9470
--- /dev/null
+++ b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2014-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.jackson2;
+
+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;
+
+/**
+ * Jackson mixin class to serialize/deserialize
+ * {@link org.springframework.security.web.authentication.WebAuthenticationDetails}.
+ *
+ *
+ * ObjectMapper mapper = new ObjectMapper();
+ * mapper.registerModule(new WebJackson2Module());
+ *
+ *
+ * @author Jitendra Singh
+ * @see WebJackson2Module
+ * @see org.springframework.security.jackson2.SecurityJacksonModules
+ * @since 4.2
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.ANY)
+class WebAuthenticationDetailsMixin {
+
+ @JsonCreator
+ WebAuthenticationDetailsMixin(@JsonProperty("remoteAddress") String remoteAddress,
+ @JsonProperty("sessionId") String sessionId) {
+ }
+}
diff --git a/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/WebJackson2Module.java b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/WebJackson2Module.java
new file mode 100644
index 00000000..5a86502d
--- /dev/null
+++ b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/WebJackson2Module.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2014-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.jackson2;
+
+import javax.servlet.http.Cookie;
+
+import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+import org.springframework.security.jackson2.SecurityJacksonModules;
+import org.springframework.security.web.authentication.WebAuthenticationDetails;
+import org.springframework.security.web.csrf.DefaultCsrfToken;
+import org.springframework.security.web.savedrequest.DefaultSavedRequest;
+import org.springframework.security.web.savedrequest.SavedCookie;
+
+/**
+ * Jackson module for spring-security-web. This module register {@link CookieMixin},
+ * {@link DefaultCsrfTokenMixin}, {@link DefaultSavedRequestMixin} and
+ * {@link WebAuthenticationDetailsMixin}. 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.
+ *
+ *
+ * ObjectMapper mapper = new ObjectMapper();
+ * mapper.registerModule(new WebJackson2Module());
+ *
Note: use {@link SecurityJacksonModules#getModules(ClassLoader)} to get list
+ * of all security modules.
+ *
+ * @author Jitendra Singh
+ * @see SecurityJacksonModules
+ */
+public class WebJackson2Module extends SimpleModule {
+
+ public WebJackson2Module() {
+ super(WebJackson2Module.class.getName(), new Version(1, 0, 0, null, null, null));
+ }
+
+ @Override
+ public void setupModule(SetupContext context) {
+ SecurityJacksonModules.enableDefaultTyping((ObjectMapper) context.getOwner());
+ context.setMixInAnnotations(Cookie.class, CookieMixin.class);
+ context.setMixInAnnotations(SavedCookie.class, SavedCookieMixin.class);
+ context.setMixInAnnotations(DefaultCsrfToken.class, DefaultCsrfTokenMixin.class);
+ context.setMixInAnnotations(DefaultSavedRequest.class,
+ DefaultSavedRequestMixin.class);
+ context.setMixInAnnotations(WebAuthenticationDetails.class,
+ WebAuthenticationDetailsMixin.class);
+ }
+}
diff --git a/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/package-info.java b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/package-info.java
new file mode 100644
index 00000000..f65eabb7
--- /dev/null
+++ b/samples/httpsession-redis-json/src/main/java/org/springframework/security/web/jackson2/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2014-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.
+ */
+
+/**
+ * Mix-in classes to provide Jackson serialization support.
+ *
+ * @author Jitendra Singh
+ * @since 4.2
+ */
+package org.springframework.security.web.jackson2;
diff --git a/samples/httpsession-redis-json/src/main/java/sample/mixins/BadCredentialsExceptionMixin.java b/samples/httpsession-redis-json/src/main/java/sample/mixins/BadCredentialsExceptionMixin.java
deleted file mode 100644
index a126b3d3..00000000
--- a/samples/httpsession-redis-json/src/main/java/sample/mixins/BadCredentialsExceptionMixin.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package sample.mixins;
-
-import com.fasterxml.jackson.annotation.*;
-
-/**
- * @author jitendra on 15/3/16.
- */
-@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
-@JsonIgnoreProperties({"cause", "@id"})
-public class BadCredentialsExceptionMixin {
-
- @JsonCreator
- public BadCredentialsExceptionMixin(@JsonProperty("detailMessage") String msg) {
- }
-}
diff --git a/samples/httpsession-redis-json/src/main/java/sample/mixins/DefaultCsrfTokenMixin.java b/samples/httpsession-redis-json/src/main/java/sample/mixins/DefaultCsrfTokenMixin.java
deleted file mode 100644
index 23153eb0..00000000
--- a/samples/httpsession-redis-json/src/main/java/sample/mixins/DefaultCsrfTokenMixin.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package sample.mixins;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import org.springframework.security.web.PortResolver;
-
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * @author jitendra on 8/3/16.
- */
-@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
-public abstract class DefaultCsrfTokenMixin {
-
- @JsonCreator
- public DefaultCsrfTokenMixin(@JsonProperty("headerName") String headerName,
- @JsonProperty("parameterName") String parameterName,
- @JsonProperty("token") String token) {
- }
-}
diff --git a/samples/httpsession-redis-json/src/main/java/sample/mixins/DefaultSavedRequestDeserializer.java b/samples/httpsession-redis-json/src/main/java/sample/mixins/DefaultSavedRequestDeserializer.java
deleted file mode 100644
index 7ed0369f..00000000
--- a/samples/httpsession-redis-json/src/main/java/sample/mixins/DefaultSavedRequestDeserializer.java
+++ /dev/null
@@ -1,262 +0,0 @@
-package sample.mixins;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-import com.sun.org.apache.xpath.internal.operations.Bool;
-import org.springframework.security.web.PortResolverImpl;
-import org.springframework.security.web.savedrequest.DefaultSavedRequest;
-import org.springframework.security.web.savedrequest.SavedCookie;
-import org.springframework.util.ObjectUtils;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-import javax.servlet.http.HttpSession;
-import java.io.IOException;
-import java.lang.reflect.Proxy;
-import java.util.*;
-
-/**
- * @author jitendra on 8/3/16.
- */
-public class DefaultSavedRequestDeserializer extends StdDeserializer {
-
- public DefaultSavedRequestDeserializer(Class requestClass) {
- super(requestClass);
- }
-
- @Override
- public DefaultSavedRequest deserialize(JsonParser p, DeserializationContext context) throws IOException, JsonProcessingException {
- ObjectMapper mapper = (ObjectMapper) p.getCodec();
- JsonNode jsonNode = mapper.readTree(p);
- DummyServletRequest request = new DummyServletRequest();
- request.setContextPath(jsonNode.get("contextPath").asText());
- request.setMethod(jsonNode.get("method").asText());
- request.setPathInfo(jsonNode.get("pathInfo").asText());
- request.setQueryString(jsonNode.get("queryString").asText());
- request.setRequestURI(jsonNode.get("requestURI").asText());
- request.setRequestURL(jsonNode.get("requestURL").asText());
- request.setScheme(jsonNode.get("scheme").asText());
- request.setServerName(jsonNode.get("serverName").asText());
- request.setServletPath(jsonNode.get("servletPath").asText());
- request.setServerPort(jsonNode.get("serverPort").asInt());
- List cookies = mapper.readValue(jsonNode.get("cookies").toString(), new TypeReference>() {
- });
- Map params = mapper.readValue(jsonNode.get("parameterMap").toString(), new TypeReference