From 3a6e5be8a0c08b404168fac0f9be5fe39577a2ac Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Wed, 30 Mar 2016 18:05:30 +0530 Subject: [PATCH 01/62] JSONAssert version property added --- gradle/javaprojects.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/gradle/javaprojects.gradle b/gradle/javaprojects.gradle index 1a3c4ac97c0..8d973e39fd6 100644 --- a/gradle/javaprojects.gradle +++ b/gradle/javaprojects.gradle @@ -34,6 +34,7 @@ ext.springDataJpaVersion = '1.7.1.RELEASE' ext.springDataRedisVersion = '1.4.1.RELEASE' ext.springSessionVersion = '1.0.0.RELEASE' ext.thymeleafVersion = '2.1.4.RELEASE' +ext.jsonassertVersion = '1.3.0' ext.spockDependencies = [ dependencies.create("org.spockframework:spock-spring:$spockVersion") { From 434feedb97ea7c360289d7c03673616bcd110bb3 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Tue, 5 Apr 2016 21:33:06 +0530 Subject: [PATCH 02/62] Jackson and JSONAssert dependencies added --- web/web.gradle | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/web/web.gradle b/web/web.gradle index a525bfef8c7..4bd07fa22b7 100644 --- a/web/web.gradle +++ b/web/web.gradle @@ -11,7 +11,8 @@ dependencies { optional "org.springframework:spring-webmvc:$springVersion", "org.springframework:spring-jdbc:$springVersion", - "org.springframework:spring-tx:$springVersion" + "org.springframework:spring-tx:$springVersion", + "com.fasterxml.jackson.core:jackson-databind:$jacksonDatavindVersion" provided "javax.servlet:javax.servlet-api:$servletApiVersion" @@ -20,7 +21,8 @@ dependencies { "org.slf4j:jcl-over-slf4j:$slf4jVersion", "org.codehaus.groovy:groovy-all:$groovyVersion", powerMockDependencies, - spockDependencies + spockDependencies, + "org.skyscreamer:jsonassert:$jsonassertVersion" testRuntime "org.hsqldb:hsqldb:$hsqlVersion" } \ No newline at end of file From cb29035c9374976e431fea4249f10c7228f9888c Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Tue, 5 Apr 2016 21:33:55 +0530 Subject: [PATCH 03/62] Jackson2 package added to add mix-in classes for web module --- .../security/web/jackson2/package-info.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 web/src/main/java/org/springframework/security/web/jackson2/package-info.java diff --git a/web/src/main/java/org/springframework/security/web/jackson2/package-info.java b/web/src/main/java/org/springframework/security/web/jackson2/package-info.java new file mode 100644 index 00000000000..72961dd4570 --- /dev/null +++ b/web/src/main/java/org/springframework/security/web/jackson2/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2002-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. + */ +package org.springframework.security.web.jackson2; \ No newline at end of file From 130729d765e9fa67192caf7319ca714797309ad9 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Tue, 5 Apr 2016 21:34:18 +0530 Subject: [PATCH 04/62] DefaultCsrfTokenMixin added --- .../web/jackson2/DefaultCsrfTokenMixin.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java diff --git a/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java new file mode 100644 index 00000000000..37c7a9dbf43 --- /dev/null +++ b/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java @@ -0,0 +1,26 @@ +package org.springframework.security.web.jackson2; + +import com.fasterxml.jackson.annotation.*; + +/** + * Mix-in class for {@link org.springframework.security.web.csrf.DefaultCsrfToken} to enable Jackson + * serialization support. + * + * @author Jitendra Singh + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") +public class DefaultCsrfTokenMixin { + + /** + * JsonCreator constructor needed by Jackson to create {@link org.springframework.security.web.csrf.DefaultCsrfToken} + * object. + * + * @param headerName + * @param parameterName + * @param token + */ + @JsonCreator + public DefaultCsrfTokenMixin(@JsonProperty("headerName") String headerName, + @JsonProperty("parameterName") String parameterName, @JsonProperty("token") String token) { + } +} From 774e6fa0e132c6a2f879a2aae9a87eaf2c23273d Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Tue, 5 Apr 2016 21:34:32 +0530 Subject: [PATCH 05/62] DefaultCsrfTokenMixin tests added --- .../jackson2/DefaultCsrfTokenMixinTests.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java diff --git a/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java new file mode 100644 index 00000000000..bcd5967cc77 --- /dev/null +++ b/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java @@ -0,0 +1,62 @@ +package org.springframework.security.web.jackson2; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.json.JSONException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.security.web.csrf.DefaultCsrfToken; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Jitendra Singh + */ +@RunWith(MockitoJUnitRunner.class) +public class DefaultCsrfTokenMixinTests { + + ObjectMapper objectMapper; + String defaultCsrfTokenJson; + + @Before + public void setup() { + objectMapper = new ObjectMapper(); + objectMapper.addMixIn(DefaultCsrfToken.class, DefaultCsrfTokenMixin.class); + defaultCsrfTokenJson = "{\"@class\": \"org.springframework.security.web.csrf.DefaultCsrfToken\", " + + "\"headerName\": \"csrf-header\", \"parameterName\": \"_csrf\", \"token\": \"1\"}"; + } + + @Test + public void defaultCsrfTokenSerializedTest() throws JsonProcessingException, JSONException { + DefaultCsrfToken token = new DefaultCsrfToken("csrf-header", "_csrf", "1"); + String serializedJson = objectMapper.writeValueAsString(token); + JSONAssert.assertEquals(defaultCsrfTokenJson, serializedJson, true); + } + + @Test + public void defaultCsrfTokenDeserializeTest() throws IOException { + DefaultCsrfToken token = objectMapper.readValue(defaultCsrfTokenJson, 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\"}"; + objectMapper.readValue(tokenJson, DefaultCsrfToken.class); + } + + @Test(expected = JsonMappingException.class) + public void defaultCsrfTokenDeserializeNullValuesTest() throws IOException { + String tokenJson = "{\"@class\": \"org.springframework.security.web.csrf.DefaultCsrfToken\", \"headerName\": \"\", \"parameterName\": null, \"token\": \"1\"}"; + objectMapper.readValue(tokenJson, DefaultCsrfToken.class); + } +} From a28b65b1aea02c82d80b9d4673ffb763e79a52b0 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Tue, 5 Apr 2016 21:35:09 +0530 Subject: [PATCH 06/62] Jackson and jsonassert dependencies added --- core/core.gradle | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/core.gradle b/core/core.gradle index c2866496a08..2a4a1a7f277 100644 --- a/core/core.gradle +++ b/core/core.gradle @@ -24,14 +24,16 @@ dependencies { 'javax.annotation:jsr250-api:1.0', "org.aspectj:aspectjrt:$aspectjVersion", "org.springframework:spring-jdbc:$springVersion", - "org.springframework:spring-tx:$springVersion" + "org.springframework:spring-tx:$springVersion", + "com.fasterxml.jackson.core:jackson-databind:$jacksonDatavindVersion" included cryptoProject testCompile "commons-collections:commons-collections:$commonsCollectionsVersion", "org.springframework:spring-test:$springVersion", "org.slf4j:jcl-over-slf4j:$slf4jVersion", - powerMockDependencies + powerMockDependencies, + "org.skyscreamer:jsonassert:$jsonassertVersion" testRuntime "org.hsqldb:hsqldb:$hsqlVersion" } From a9393d3b868f2934fd41451c1ccaf42587b7b260 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Tue, 5 Apr 2016 21:36:27 +0530 Subject: [PATCH 07/62] Jackson2 package added to add jackson mixin classes for this module --- .../security/jackson2/package-info.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 core/src/main/java/org/springframework/security/jackson2/package-info.java diff --git a/core/src/main/java/org/springframework/security/jackson2/package-info.java b/core/src/main/java/org/springframework/security/jackson2/package-info.java new file mode 100644 index 00000000000..a6b46f4706e --- /dev/null +++ b/core/src/main/java/org/springframework/security/jackson2/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2002-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. + */ +package org.springframework.security.jackson2; \ No newline at end of file From 614cb5b4f5f6cd08b973484d98b6e7d9dd5929a4 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Tue, 5 Apr 2016 21:36:43 +0530 Subject: [PATCH 08/62] SimpleGrantedAuthorityMixin class added --- .../jackson2/SimpleGrantedAuthorityMixin.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java diff --git a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java new file mode 100644 index 00000000000..f7255f51f4f --- /dev/null +++ b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java @@ -0,0 +1,19 @@ +package org.springframework.security.jackson2; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +/** + * @author jitendra + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") +public abstract class SimpleGrantedAuthorityMixin { + + @JsonCreator + public SimpleGrantedAuthorityMixin(@JsonProperty("role") String role) { + } + + @JsonProperty("role") + public abstract String getAuthority(); +} From 731d23234a93093fde0ee27fa9686c94ced9c9be Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 14:32:12 +0800 Subject: [PATCH 09/62] Mixin added for WebAuthenticationDetails --- .../WebAuthenticationDetails.java | 11 +++ .../WebAuthenticationDetailsMixin.java | 17 +++++ .../WebAuthenticationDetailsMixinTest.java | 67 +++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java create mode 100644 web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java diff --git a/web/src/main/java/org/springframework/security/web/authentication/WebAuthenticationDetails.java b/web/src/main/java/org/springframework/security/web/authentication/WebAuthenticationDetails.java index 2d0f1d6c838..a2675c60540 100644 --- a/web/src/main/java/org/springframework/security/web/authentication/WebAuthenticationDetails.java +++ b/web/src/main/java/org/springframework/security/web/authentication/WebAuthenticationDetails.java @@ -54,6 +54,17 @@ public WebAuthenticationDetails(HttpServletRequest request) { this.sessionId = (session != null) ? session.getId() : null; } + /** + * Constructor to add Jackson2 serialize/deserialize support + * + * @param remoteAddress remote address of current request + * @param sessionId session id + */ + private WebAuthenticationDetails(final String remoteAddress, final String sessionId) { + this.remoteAddress = remoteAddress; + this.sessionId = sessionId; + } + // ~ Methods // ======================================================================================================== diff --git a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java new file mode 100644 index 00000000000..1ea8bf0f7c4 --- /dev/null +++ b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java @@ -0,0 +1,17 @@ +package org.springframework.security.web.jackson2; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +/** + * @author Jitendra Singh + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +public class WebAuthenticationDetailsMixin { + + @JsonCreator + WebAuthenticationDetailsMixin(@JsonProperty("remoteAddress") String remoteAddress, + @JsonProperty("sessionId") String sessionId) { + } +} diff --git a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java new file mode 100644 index 00000000000..b367cc9983e --- /dev/null +++ b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java @@ -0,0 +1,67 @@ +package org.springframework.security.web.jackson2; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.json.JSONException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.security.web.authentication.WebAuthenticationDetails; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.*; + +/** + * @author Jitendra Singh + */ +@RunWith(MockitoJUnitRunner.class) +public class WebAuthenticationDetailsMixinTest { + + ObjectMapper mapper; + + @Before + public void setup() { + mapper = new ObjectMapper() + .addMixIn(WebAuthenticationDetails.class, WebAuthenticationDetailsMixin.class); + } + + @Test + public void buildWebAuthenticationDetailsUsingDifferentConstructors() throws IOException { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setRemoteAddr("localhost"); + request.setSession(new MockHttpSession(null, "1")); + + WebAuthenticationDetails details = new WebAuthenticationDetails(request); + String jsonString = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + + "\"sessionId\": \"1\", \"remoteAddress\": \"/localhost\"}"; + WebAuthenticationDetails authenticationDetails = mapper.readValue(jsonString, WebAuthenticationDetails.class); + assertThat(details.equals(authenticationDetails)); + } + + @Test + public void webAuthenticationDetailsSerializeTest() throws JsonProcessingException, JSONException { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setRemoteAddr("/home"); + request.setSession(new MockHttpSession(null, "1")); + WebAuthenticationDetails details = new WebAuthenticationDetails(request); + String expectedJson = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + + "\"sessionId\": \"1\", \"remoteAddress\": \"/home\"}"; + String actualJson = mapper.writeValueAsString(details); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } + + @Test + public void webAuthenticationDetailsDeserializeTest() throws IOException, JSONException { + String actualJson = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + + "\"sessionId\": \"1\", \"remoteAddress\": \"/home\"}"; + WebAuthenticationDetails details = mapper.readValue(actualJson, WebAuthenticationDetails.class); + assertThat(details).isNotNull(); + assertThat(details.getRemoteAddress()).isEqualTo("/home"); + assertThat(details.getSessionId()).isEqualTo("1"); + } +} From f808de2a86c9bad93a8fb0777c569a25fdf8844e Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 14:36:58 +0800 Subject: [PATCH 10/62] Builder class added with private Constructor --- .../web/savedrequest/DefaultSavedRequest.java | 178 +++++++++++++++--- 1 file changed, 152 insertions(+), 26 deletions(-) diff --git a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java index 1ac42d7a455..f70294a61e1 100644 --- a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java +++ b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java @@ -84,13 +84,7 @@ public DefaultSavedRequest(HttpServletRequest request, PortResolver portResolver Assert.notNull(portResolver, "PortResolver required"); // Cookies - Cookie[] cookies = request.getCookies(); - - if (cookies != null) { - for (Cookie cookie : cookies) { - this.addCookie(cookie); - } - } + addCookies(request.getCookies()); // Headers Enumeration names = request.getHeaderNames(); @@ -110,27 +104,10 @@ public DefaultSavedRequest(HttpServletRequest request, PortResolver portResolver } // Locales - Enumeration locales = request.getLocales(); - - while (locales.hasMoreElements()) { - Locale locale = (Locale) locales.nextElement(); - this.addLocale(locale); - } + addLocales(request.getLocales()); // Parameters - Map parameters = request.getParameterMap(); - - for (String paramName : parameters.keySet()) { - Object paramValues = parameters.get(paramName); - if (paramValues instanceof String[]) { - this.addParameter(paramName, (String[]) paramValues); - } - else { - if (logger.isWarnEnabled()) { - logger.warn("ServletRequest.getParameterMap() returned non-String array"); - } - } - } + addParameters(request.getParameterMap()); // Primitives this.method = request.getMethod(); @@ -145,9 +122,35 @@ public DefaultSavedRequest(HttpServletRequest request, PortResolver portResolver this.servletPath = request.getServletPath(); } + /** + * Private constructor invoked through Builder + */ + private DefaultSavedRequest(String contextPath, String method, String pathInfo, String queryString, String requestURI, + String requestURL, String scheme, String serverName, String servletPath, int serverPort) { + + this.contextPath = contextPath; + this.method = method; + this.pathInfo = pathInfo; + this.queryString = queryString; + this.requestURI = requestURI; + this.requestURL = requestURL; + this.scheme = scheme; + this.serverName = serverName; + this.servletPath = servletPath; + this.serverPort = serverPort; + } + // ~ Methods // ======================================================================================================== + private void addCookies(Cookie[] cookies) { + if (cookies != null) { + for (Cookie cookie : cookies) { + this.addCookie(cookie); + } + } + } + private void addCookie(Cookie cookie) { cookies.add(new SavedCookie(cookie)); } @@ -163,10 +166,30 @@ private void addHeader(String name, String value) { values.add(value); } + private void addLocales(Enumeration locales) { + while (locales.hasMoreElements()) { + Locale locale = locales.nextElement(); + this.addLocale(locale); + } + } + private void addLocale(Locale locale) { locales.add(locale); } + private void addParameters(Map parameters) { + for (String paramName : parameters.keySet()) { + Object paramValues = parameters.get(paramName); + if (paramValues instanceof String[]) { + this.addParameter(paramName, (String[]) paramValues); + } else { + if (logger.isWarnEnabled()) { + logger.warn("ServletRequest.getParameterMap() returned non-String array"); + } + } + } + } + private void addParameter(String name, String[] values) { parameters.put(name, values); } @@ -316,6 +339,109 @@ public String getServletPath() { return servletPath; } + public static class Builder { + + private List cookies = null; + private List locales = null; + private Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + private Map parameters = new TreeMap(); + private String contextPath; + private String method; + private String pathInfo; + private String queryString; + private String requestURI; + private String requestURL; + private String scheme; + private String serverName; + private String servletPath; + private int serverPort = 80; + + public Builder setCookies(List cookies) { + this.cookies = cookies; + return this; + } + + public Builder setLocales(List locales) { + this.locales = locales; + return this; + } + + public Builder setHeaders(Map> header) { + this.headers.putAll(header); + return this; + } + + public Builder setParameters(Map parameters) { + this.parameters = parameters; + return this; + } + + public Builder setContextPath(String contextPath) { + this.contextPath = contextPath; + return this; + } + + public Builder setMethod(String method) { + this.method = method; + return this; + } + + public Builder setPathInfo(String pathInfo) { + this.pathInfo = pathInfo; + return this; + } + + public Builder setQueryString(String queryString) { + this.queryString = queryString; + return this; + } + + public Builder setRequestURI(String requestURI) { + this.requestURI = requestURI; + return this; + } + + public Builder setRequestURL(String requestURL) { + this.requestURL = requestURL; + return this; + } + + public Builder setScheme(String scheme) { + this.scheme = scheme; + return this; + } + + public Builder setServerName(String serverName) { + this.serverName = serverName; + return this; + } + + public Builder setServletPath(String servletPath) { + this.servletPath = servletPath; + return this; + } + + public Builder setServerPort(int serverPort) { + this.serverPort = serverPort; + return this; + } + + public DefaultSavedRequest build() { + DefaultSavedRequest savedRequest = new DefaultSavedRequest( + this.contextPath, this.method, this.pathInfo, this.queryString, this.requestURI, + this.requestURL, this.scheme, this.serverName, this.servletPath, this.serverPort + ); + savedRequest.addCookies(this.cookies.toArray(new Cookie[]{})); + savedRequest.locales.addAll(this.locales); + savedRequest.addParameters(this.parameters); + + this.headers.remove(HEADER_IF_MODIFIED_SINCE); + this.headers.remove(HEADER_IF_NONE_MATCH); + savedRequest.headers.putAll(this.headers); + return savedRequest; + } + } + private boolean propertyEquals(String log, Object arg1, Object arg2) { if ((arg1 == null) && (arg2 == null)) { if (logger.isDebugEnabled()) { From 79353ceaef5a87f4b77a375423b9bf4533cb0b02 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 14:37:21 +0800 Subject: [PATCH 11/62] Mixin added for DefaultSavedRequest --- .../jackson2/DefaultSavedRequestMixin.java | 25 ++++ .../DefaultSavedRequestMixinTest.java | 107 ++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java create mode 100644 web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java diff --git a/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java new file mode 100644 index 00000000000..53cb21b2b6c --- /dev/null +++ b/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java @@ -0,0 +1,25 @@ +package org.springframework.security.web.jackson2; + +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.web.savedrequest.DefaultSavedRequest; + +import java.util.Map; + +/** + * @author Jitendra Singh + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +@JsonDeserialize(builder = DefaultSavedRequest.Builder.class) +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY) +@JsonIgnoreProperties( + value = {"headerNames", "headerValues", "parameterNames", "redirectUrl"} +) +public abstract class DefaultSavedRequestMixin { + + @JsonProperty("parameters") + public abstract Map getParameterMap(); +} diff --git a/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java new file mode 100644 index 00000000000..bbfbe399e64 --- /dev/null +++ b/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java @@ -0,0 +1,107 @@ +package org.springframework.security.web.jackson2; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.json.JSONException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.security.web.PortResolverImpl; +import org.springframework.security.web.savedrequest.DefaultSavedRequest; + +import javax.servlet.http.Cookie; +import java.io.IOException; +import java.util.Collections; +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Jitendra Singh + */ +@RunWith(MockitoJUnitRunner.class) +public class DefaultSavedRequestMixinTest { + + ObjectMapper buildObjectMapper() { + ObjectMapper mapper = new ObjectMapper() + .enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY) + .addMixIn(DefaultSavedRequest.class, DefaultSavedRequestMixin.class) + .addMixIn(Cookie.class, CookieMixin.class); + mapper.setVisibilityChecker( + mapper.getVisibilityChecker() + .withVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) + .withVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY) + ); + return mapper; + } + + @Test + public void matchRequestBuildWithConstructorAndBuilder() { + DefaultSavedRequest request = new DefaultSavedRequest.Builder() + .setCookies(Collections.singletonList(new Cookie("SESSION", "123456789"))) + .setHeaders(Collections.singletonMap("x-auth-token", Collections.singletonList("12"))) + .setScheme("http").setRequestURL("http://localhost").setServerName("localhost").setRequestURI("") + .setLocales(Collections.singletonList(new Locale("en"))).setContextPath("").setMethod("") + .setServletPath("").build(); + MockHttpServletRequest mockRequest = new MockHttpServletRequest(); + mockRequest.setCookies(new Cookie("SESSION", "123456789")); + mockRequest.addHeader("x-auth-token", "12"); + + assert request.doesRequestMatch(mockRequest, new PortResolverImpl()); + } + + @Test + public void serializeDefaultRequestBuildWithConstructorTest() throws IOException, JSONException { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setCookies(new Cookie("SESSION", "123456789")); + request.addHeader("x-auth-token", "12"); + + String expectedJsonString = "{" + + "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}]]," + + "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + + "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + + "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ + "}"; + String actualString = buildObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(new DefaultSavedRequest(request, new PortResolverImpl())); + JSONAssert.assertEquals(expectedJsonString, actualString, true); + } + + @Test + public void serializeDefaultRequestBuildWithBuilderTest() throws IOException, JSONException { + DefaultSavedRequest request = new DefaultSavedRequest.Builder() + .setCookies(Collections.singletonList(new Cookie("SESSION", "123456789"))) + .setHeaders(Collections.singletonMap("x-auth-token", Collections.singletonList("12"))) + .setScheme("http").setRequestURL("http://localhost").setServerName("localhost").setRequestURI("") + .setLocales(Collections.singletonList(new Locale("en"))).setContextPath("").setMethod("") + .setServletPath("").build(); + + String expectedJsonString = "{" + + "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}]]," + + "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + + "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + + "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ + "}"; + String actualString = buildObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(request); + JSONAssert.assertEquals(expectedJsonString, actualString, true); + } + + @Test + public void deserializeDefaultSavedRequest() throws IOException { + String jsonString = "{" + + "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}]]," + + "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + + "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + + "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ + "}"; + DefaultSavedRequest request = buildObjectMapper().readValue(jsonString, DefaultSavedRequest.class); + assertThat(request).isNotNull(); + assertThat(request.getCookies()).hasSize(1); + assertThat(request.getLocales()).hasSize(1).contains(new Locale("en")); + assertThat(request.getHeaderNames()).hasSize(1).contains("x-auth-token"); + assertThat(request.getHeaderValues("x-auth-token")).hasSize(1).contains("12"); + } +} From 30f42b75127fe37164e190433152a7b937b5aa08 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 14:38:05 +0800 Subject: [PATCH 12/62] Http Cookie mixins and Deserializer added --- .../web/jackson2/CookieDeserializer.java | 38 ++++++++++++++++ .../security/web/jackson2/CookieMixin.java | 20 +++++++++ .../web/jackson2/CookieMixinTest.java | 43 +++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java create mode 100644 web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java create mode 100644 web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java diff --git a/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java b/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java new file mode 100644 index 00000000000..c2f35b20b2e --- /dev/null +++ b/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java @@ -0,0 +1,38 @@ +package org.springframework.security.web.jackson2; + +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; + +import javax.servlet.http.Cookie; +import java.io.IOException; + +/** + * @author Jitendra Singh + */ +public 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, "isHttpOnly").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/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java new file mode 100644 index 00000000000..7c1f6c36837 --- /dev/null +++ b/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java @@ -0,0 +1,20 @@ +package org.springframework.security.web.jackson2; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +/** + * @author Jitendra Singh + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +@JsonDeserialize(using = CookieDeserializer.class) +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE) +public abstract class CookieMixin { + + @JsonCreator + public CookieMixin(@JsonProperty("name") String name, @JsonProperty("value") String value) { + } +} diff --git a/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java new file mode 100644 index 00000000000..8e89612ec8b --- /dev/null +++ b/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java @@ -0,0 +1,43 @@ +package org.springframework.security.web.jackson2; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.json.JSONException; +import org.junit.Test; +import org.skyscreamer.jsonassert.JSONAssert; + +import javax.servlet.http.Cookie; +import java.io.IOException; + +import static org.assertj.core.api.Assertions.*; + +/** + * @author Jitendra Singh + */ +public class CookieMixinTest { + + ObjectMapper buildObjectMapper() { + return new ObjectMapper() + .addMixIn(Cookie.class, CookieMixin.class); + } + + @Test + public void serializeCookie() throws JsonProcessingException, JSONException { + Cookie cookie = new Cookie("demo", "cookie1"); + String expectedString = "{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"demo\", \"value\": \"cookie1\"," + + "\"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\": false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}"; + String actualString = buildObjectMapper().writeValueAsString(cookie); + JSONAssert.assertEquals(expectedString, actualString, true); + } + + @Test + public void deserializeCookie() throws IOException { + String cookieString = "{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"demo\", \"value\": \"cookie1\"," + + "\"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\": false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}"; + Cookie cookie = buildObjectMapper().readValue(cookieString, Cookie.class); + assertThat(cookie).isNotNull(); + assertThat(cookie.getName()).isEqualTo("demo"); + assertThat(cookie.getDomain()).isEqualTo(""); + assertThat(cookie.isHttpOnly()).isEqualTo(false); + } +} From 16a91043646b14e25257ccb2338bb3dc876adc89 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 14:39:03 +0800 Subject: [PATCH 13/62] SecurityContext Tests added --- .../jackson2/SecurityContextMixinTest.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java diff --git a/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java new file mode 100644 index 00000000000..be7d341931f --- /dev/null +++ b/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java @@ -0,0 +1,60 @@ +package org.springframework.security.jackson2; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.json.JSONException; +import org.junit.Test; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextImpl; + +import java.io.IOException; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.*; + +/** + * @author Jitendra Singh + */ +public class SecurityContextMixinTest extends AbstractMixinTests { + + @Override + protected ObjectMapper buildObjectMapper() { + return super.buildObjectMapper() + .addMixIn(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class) + .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class); + } + + @Test + public void securityContextSerializeTest() throws JsonProcessingException, JSONException { + String expectedJson = "{\"@class\": \"org.springframework.security.core.context.SecurityContextImpl\", \"authentication\": " + + "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + "\"principal\": \"user\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, \"name\": \"user\"," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]" + + "}" + + "}"; + SecurityContext context = new SecurityContextImpl(); + context.setAuthentication(new UsernamePasswordAuthenticationToken("user", "password", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")))); + String actualJson = buildObjectMapper().writeValueAsString(context); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } + + @Test + public void securityContextDeserializeTest() throws IOException { + String contextJson = "{\"@class\": \"org.springframework.security.core.context.SecurityContextImpl\", \"authentication\": " + + "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + "\"principal\": \"user\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, \"name\": \"user\"," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]" + + "}" + + "}"; + SecurityContext context = buildObjectMapper().readValue(contextJson, SecurityContextImpl.class); + assertThat(context).isNotNull(); + assertThat(context.getAuthentication()).isNotNull().isInstanceOf(UsernamePasswordAuthenticationToken.class); + assertThat(context.getAuthentication().getPrincipal()).isEqualTo("user"); + assertThat(context.getAuthentication().getCredentials()).isEqualTo("password"); + assertThat(context.getAuthentication().isAuthenticated()).isEqualTo(true); + assertThat(context.getAuthentication().getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + } +} From 715065ccccb6648d7296732a64d14aec359a3928 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 14:40:10 +0800 Subject: [PATCH 14/62] UsernamePasswordAuthenticationToken mixins, deserializer and test added --- ...sswordAuthenticationTokenDeserializer.java | 52 +++++++++ ...rnamePasswordAuthenticationTokenMixin.java | 12 ++ ...ePasswordAuthenticationTokenMixinTest.java | 105 ++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java create mode 100644 core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java create mode 100644 core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java diff --git a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java new file mode 100644 index 00000000000..52e00ed7ab2 --- /dev/null +++ b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java @@ -0,0 +1,52 @@ +package org.springframework.security.jackson2; + +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; + +import java.io.IOException; +import java.util.List; + +/** + * @author Jitendra Singh + */ +public class UsernamePasswordAuthenticationTokenDeserializer extends JsonDeserializer { + + @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/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java new file mode 100644 index 00000000000..5b531177b49 --- /dev/null +++ b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java @@ -0,0 +1,12 @@ +package org.springframework.security.jackson2; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +/** + * @author Jitendra Singh + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") +@JsonDeserialize(using = UsernamePasswordAuthenticationTokenDeserializer.class) +public abstract class UsernamePasswordAuthenticationTokenMixin { +} diff --git a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java new file mode 100644 index 00000000000..1dd49a05f77 --- /dev/null +++ b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java @@ -0,0 +1,105 @@ +package org.springframework.security.jackson2; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.json.JSONException; +import org.junit.Test; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; + +import java.io.IOException; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Jitendra Singh + */ +public class UsernamePasswordAuthenticationTokenMixinTest extends AbstractMixinTests { + + @Override + protected ObjectMapper buildObjectMapper() { + return super.buildObjectMapper() + .addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class) + .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) + .addMixIn(User.class, UserMixin.class) + .addMixIn(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class); + } + + @Test + public void serializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws JsonProcessingException, JSONException { + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + " \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": false, \"details\": null, " + + "\"authorities\": [\"java.util.ArrayList\", []], \"name\": \"user1\"}"; + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user1", "password"); + String serializedJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, serializedJson, true); + } + + @Test + public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws JsonProcessingException, JSONException { + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + " \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, " + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]], \"name\": \"user1\"}"; + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user1", "password", Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"))); + String serializedJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, serializedJson, true); + } + + @Test + public void deserializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws IOException, JSONException { + String tokenJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + " \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": false, \"details\": null, " + + "\"authorities\": [\"java.util.ArrayList\", []], \"name\": \"user1\"}"; + UsernamePasswordAuthenticationToken token = buildObjectMapper().readValue(tokenJson, UsernamePasswordAuthenticationToken.class); + assertThat(token).isNotNull(); + assertThat(token.isAuthenticated()).isEqualTo(false); + assertThat(token.getAuthorities()).isNotNull().hasSize(0); + } + + @Test + public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws IOException { + String tokenJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + "\"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, " + + "\"authorities\" : [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + UsernamePasswordAuthenticationToken token = buildObjectMapper().readValue(tokenJson, UsernamePasswordAuthenticationToken.class); + assertThat(token).isNotNull(); + assertThat(token.isAuthenticated()).isEqualTo(true); + assertThat(token.getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + } + + @Test + public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinWithUserTest() throws JsonProcessingException, JSONException { + GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); + User user = new User("user", "pass", Collections.singleton(authority)); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, "pass", Collections.singleton(authority)); + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": true, \"enabled\": true, " + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + + "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"credentials\": \"pass\"," + + "\"details\": null, \"name\": \"user\", \"authenticated\": true," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + String actualJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } + + @Test + public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenWithUserTest() throws IOException { + String tokenJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": true, \"enabled\": true, " + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + + "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"credentials\": \"pass\"," + + "\"details\": null, \"name\": \"user\", \"authenticated\": true," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + ObjectMapper mapper = buildObjectMapper(); + UsernamePasswordAuthenticationToken token = mapper.readValue(tokenJson, UsernamePasswordAuthenticationToken.class); + assertThat(token).isNotNull(); + assertThat(token.getPrincipal()).isNotNull().isInstanceOf(User.class); + assertThat(((User)token.getPrincipal()).getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + assertThat(token.isAuthenticated()).isEqualTo(true); + assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + } +} From a2c41dec08d1bd24de2834e80b71842aa71915b6 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 14:57:16 +0800 Subject: [PATCH 15/62] User mixin, deserializer and tests added --- .../security/jackson2/UserDeserializer.java | 40 ++++++++ .../security/jackson2/UserMixin.java | 22 +++++ .../jackson2/UserDeserializerTests.java | 92 +++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java create mode 100644 core/src/main/java/org/springframework/security/jackson2/UserMixin.java create mode 100644 core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java diff --git a/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java b/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java new file mode 100644 index 00000000000..b6728d1b9db --- /dev/null +++ b/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java @@ -0,0 +1,40 @@ +package org.springframework.security.jackson2; + +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.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; + +import java.io.IOException; +import java.util.Set; + +/** + * @author Jitendra Singh + */ +public class UserDeserializer extends JsonDeserializer { + + @Override + public User deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + ObjectMapper mapper = (ObjectMapper) jp.getCodec(); + JsonNode jsonNode = mapper.readTree(jp); + Set authorities = mapper.convertValue(jsonNode.get("authorities"), new TypeReference>() { + }); + return new User( + readJsonNode(jsonNode, "username").asText(), readJsonNode(jsonNode, "password").asText(""), + readJsonNode(jsonNode, "enabled").asBoolean(), readJsonNode(jsonNode, "accountNonExpired").asBoolean(), + readJsonNode(jsonNode, "credentialsNonExpired").asBoolean(), + readJsonNode(jsonNode, "accountNonLocked").asBoolean(), authorities + ); + } + + private JsonNode readJsonNode(JsonNode jsonNode, String field) { + return jsonNode.has(field) ? jsonNode.get(field) : MissingNode.getInstance(); + } +} diff --git a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java new file mode 100644 index 00000000000..e805cd8bdc4 --- /dev/null +++ b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java @@ -0,0 +1,22 @@ +package org.springframework.security.jackson2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Collection; + +/** + * @author Jitendra Singh + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +@JsonDeserialize(using = UserDeserializer.class) +public abstract class UserMixin { + + public UserMixin(@JsonProperty("username") String username, @JsonProperty("password") String password, + @JsonProperty("enabled") boolean enabled, @JsonProperty("accountNonExpired") boolean accountNonExpired, + @JsonProperty("credentialsNonExpired") boolean credentialsNonExpired, + @JsonProperty("accountNonLocked") boolean accountNonLocked, @JsonProperty("authorities") Collection authorities) { + } +} diff --git a/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java b/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java new file mode 100644 index 00000000000..a7cc3a32883 --- /dev/null +++ b/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java @@ -0,0 +1,92 @@ +package org.springframework.security.jackson2; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.json.JSONException; +import org.junit.Test; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; + +import java.io.IOException; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Jitendra Singh + */ +public class UserDeserializerTests extends AbstractMixinTests { + + protected ObjectMapper buildObjectMapper() { + return super.buildObjectMapper() + .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) + .addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class) + .addMixIn(User.class, UserMixin.class); + } + + @Test + public void serializeUserTest() throws JsonProcessingException, JSONException { + ObjectMapper mapper = buildObjectMapper(); + User user = new User("admin", "1234", Collections.singletonList(new SimpleGrantedAuthority("USER_ROLE"))); + String userJson = mapper.writeValueAsString(user); + String expectedJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"admin\", \"password\": \"1234\", \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"USER_ROLE\"}]]}"; + JSONAssert.assertEquals(expectedJson, userJson, true); + } + + @Test + public void serializeUserWithoutAuthority() throws JsonProcessingException, JSONException { + ObjectMapper mapper = buildObjectMapper(); + User user = new User("admin", "1234", Collections.emptyList()); + String userJson = mapper.writeValueAsString(user); + String expectedJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"admin\", \"password\": \"1234\", \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", []]}"; + JSONAssert.assertEquals(expectedJson, userJson, true); + } + + @Test(expected = IllegalArgumentException.class) + public void deserializeUserWithNullPasswordEmptyAuthorityTest() throws IOException { + String userJsonWithoutPasswordString = "{\"@class\": \"org.springframework.security.core.userdetails.User\", " + + "\"username\": \"user\", \"accountNonExpired\": true, " + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, " + + "\"authorities\": []}"; + ObjectMapper mapper = buildObjectMapper(); + mapper.readValue(userJsonWithoutPasswordString, User.class); + } + + @Test + public void deserializeUserWithNullPasswordNoAuthorityTest() throws IOException { + String userJsonWithoutPasswordString = "{\"@class\": \"org.springframework.security.core.userdetails.User\", " + + "\"username\": \"user\", \"accountNonExpired\": true, " + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, " + + "\"authorities\": [\"java.util.HashSet\", []]}"; + ObjectMapper mapper = buildObjectMapper(); + User user = mapper.readValue(userJsonWithoutPasswordString, User.class); + assertThat(user).isNotNull(); + assertThat(user.getUsername()).isEqualTo("user"); + assertThat(user.getPassword()).isEqualTo(""); + assertThat(user.getAuthorities()).hasSize(0); + assertThat(user.isEnabled()).isEqualTo(true); + } + + @Test(expected = IllegalArgumentException.class) + public void deserializeUserWithNoClassIdInAuthoritiesTest() throws IOException { + String userJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", " + + "\"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": false, " + + "\"accountNonLocked\": false, \"credentialsNonExpired\": false, \"enabled\": false, " + + "\"authorities\": [{\"role\": \"ROLE_USER\"}]}"; + buildObjectMapper().readValue(userJson, User.class); + } + + @Test + public void deserializeUserWithClassIdInAuthoritiesTest() throws IOException { + String userJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", " + + "\"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": true, " + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, " + + "\"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + User user = buildObjectMapper().readValue(userJson, User.class); + assertThat(user).isNotNull(); + assertThat(user.getUsername()).isEqualTo("user"); + assertThat(user.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + } +} From 0df66e4e78ff045f10f808ae3b577d4dcab85fb5 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 14:58:10 +0800 Subject: [PATCH 16/62] Unmodifiable tests added --- .../security/jackson2/UnmodifiableSetMixin.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java diff --git a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java new file mode 100644 index 00000000000..ef7347ec7d0 --- /dev/null +++ b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java @@ -0,0 +1,16 @@ +package org.springframework.security.jackson2; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +import java.util.Set; + +/** + * @author Jitendra Singh + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +public class UnmodifiableSetMixin { + + @JsonCreator + UnmodifiableSetMixin(Set s) {} +} From bb95f251055d30c148fe89d5afeabb7f7ad64888 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 15:09:25 +0800 Subject: [PATCH 17/62] Mixin and Tests added for SimpleGrantedAuthority --- .../jackson2/SimpleGrantedAuthorityMixin.java | 13 +++-- .../SimpleGrantedAuthorityMixinTest.java | 52 +++++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java diff --git a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java index f7255f51f4f..22d3a6a2d8a 100644 --- a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java @@ -1,13 +1,16 @@ package org.springframework.security.jackson2; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Collection; /** - * @author jitendra + * @author Jitendra Singh */ -@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +@JsonIgnoreProperties(ignoreUnknown = true) public abstract class SimpleGrantedAuthorityMixin { @JsonCreator diff --git a/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java new file mode 100644 index 00000000000..539b1c1b223 --- /dev/null +++ b/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java @@ -0,0 +1,52 @@ +package org.springframework.security.jackson2; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.json.JSONException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.security.core.authority.SimpleGrantedAuthority; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.*; + +/** + * @author Jitendra Singh. + */ +public class SimpleGrantedAuthorityMixinTest { + + ObjectMapper mapper; + + @Before + public void setup() { + mapper = new ObjectMapper(); + mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class); + } + + @Test + public void serializeSimpleGrantedAuthorityTest() throws JsonProcessingException, JSONException { + SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); + String serializeJson = mapper.writeValueAsString(authority); + String expectedJson = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}"; + JSONAssert.assertEquals(expectedJson, serializeJson, true); + } + + @Test + public void deserializeGrantedAuthorityTest() throws IOException { + String json = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}"; + SimpleGrantedAuthority authority = mapper.readValue(json, SimpleGrantedAuthority.class); + assertThat(authority).isNotNull(); + assertThat(authority.getAuthority()).isNotNull().isEqualTo("ROLE_USER"); + } + + @Test(expected = JsonMappingException.class) + public void deserializeGrantedAuthorityWithoutRoleTest() throws IOException { + String json = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\"}"; + mapper.readValue(json, SimpleGrantedAuthority.class); + } +} From 1d94aed48d5ed77ddc02bc2fecd4f27b10af069c Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 15:10:11 +0800 Subject: [PATCH 18/62] Private Constructor added to enabled enable deserialization support --- .../RememberMeAuthenticationToken.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java index fa5007fb6c8..de0fc50beb5 100644 --- a/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java @@ -67,6 +67,22 @@ public RememberMeAuthenticationToken(String key, Object principal, setAuthenticated(true); } + /** + * Private Constructor to help in Jackson deserialization. + * + * @param keyHash hashCode of above given key. + * @param principal the principal (typically a UserDetails) + * @param authorities the authorities granted to the principal + */ + private RememberMeAuthenticationToken(Integer keyHash, Object principal, + Collection authorities) { + super(authorities); + + this.keyHash = keyHash; + this.principal = principal; + setAuthenticated(true); + } + // ~ Methods // ======================================================================================================== From aeb8cb1fabe3867a4b1474a76eba1ff493b063ae Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 15:11:28 +0800 Subject: [PATCH 19/62] AbstractMixinTests added with default ObjectMapper --- .../security/jackson2/AbstractMixinTests.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java diff --git a/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java new file mode 100644 index 00000000000..5c2f63c95a5 --- /dev/null +++ b/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java @@ -0,0 +1,22 @@ +package org.springframework.security.jackson2; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; + +/** + * @author Jitenra Singh + */ +@RunWith(MockitoJUnitRunner.class) +public abstract class AbstractMixinTests { + + protected ObjectMapper buildObjectMapper() { + ObjectMapper mapper = new ObjectMapper() + .enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); + mapper.setVisibilityChecker(mapper.getVisibilityChecker().withVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)); + return mapper; + } +} From 3e6fcfabcf97d7e8984d8325716cdc881000701e Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 15:12:58 +0800 Subject: [PATCH 20/62] Mixin and tests added for RememberMeAuthenticationToken --- .../RememberMeAuthenticationTokenMixin.java | 23 +++++ ...ememberMeAuthenticationTokenMixinTest.java | 93 +++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java create mode 100644 core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java diff --git a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java new file mode 100644 index 00000000000..b69cfb4984a --- /dev/null +++ b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java @@ -0,0 +1,23 @@ +package org.springframework.security.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; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Collection; + +/** + * @author Jitendra Singh + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +@JsonIgnoreProperties(ignoreUnknown = true) +public class RememberMeAuthenticationTokenMixin { + + @JsonCreator + public RememberMeAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, + @JsonProperty("principal") Object principal, + @JsonProperty("authorities") Collection authorities) { + } +} diff --git a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java new file mode 100644 index 00000000000..953635d48cd --- /dev/null +++ b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java @@ -0,0 +1,93 @@ +package org.springframework.security.jackson2; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.json.JSONException; +import org.junit.Test; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.security.authentication.RememberMeAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Jitendra Singh + */ +public class RememberMeAuthenticationTokenMixinTest extends AbstractMixinTests { + + @Override + public ObjectMapper buildObjectMapper() { + return super.buildObjectMapper() + .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) + .addMixIn(User.class, UserMixin.class) + .addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class) + .addMixIn(RememberMeAuthenticationToken.class, RememberMeAuthenticationTokenMixin.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testWithNullPrincipal() throws JsonProcessingException, JSONException { + new RememberMeAuthenticationToken("key", null, Collections.emptyList()); + } + + @Test(expected = IllegalArgumentException.class) + public void testWithNullKey() throws JsonProcessingException, JSONException { + new RememberMeAuthenticationToken(null, "principal", Collections.emptyList()); + } + + @Test + public void serializeRememberMeAuthenticationToken() throws JsonProcessingException, JSONException { + String key = "rememberMe"; + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(key, "user", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + + "\"keyHash\": "+key.hashCode()+", \"principal\": \"user\", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + String actualJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } + + @Test + public void serializeRememberMeAuthenticationWithUserToken() throws JsonProcessingException, JSONException { + String key = "rememberMe"; + List authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(key, new User("user", "password", authorities), authorities); + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + + "\"keyHash\": "+key.hashCode()+", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"password\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]},"+ + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + String actualJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } + + @Test + public void deserializeRememberMeAuthenticationToken() throws IOException { + String key = "rememberMe"; + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + + "\"keyHash\": "+key.hashCode()+", \"principal\": \"user\", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + RememberMeAuthenticationToken token = buildObjectMapper().readValue(expectedJson, RememberMeAuthenticationToken.class); + assertThat(token).isNotNull(); + assertThat(token.getPrincipal()).isNotNull().isEqualTo("user").isEqualTo(token.getName()); + assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + } + + @Test + public void deserializeRememberMeAuthenticationTokenWithUserTest() throws IOException { + String key = "rememberMe"; + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + + "\"keyHash\": "+key.hashCode()+", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"password\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]},"+ + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + RememberMeAuthenticationToken token = buildObjectMapper().readValue(expectedJson, RememberMeAuthenticationToken.class); + assertThat(token).isNotNull(); + assertThat(token.getPrincipal()).isNotNull().isInstanceOf(User.class); + assertThat(((User)token.getPrincipal()).getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + assertThat(((User)token.getPrincipal()).isEnabled()).isEqualTo(true); + } +} From 14906c98d93343ff2e8c6f1d5b25100d2ea2a938 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 15:14:54 +0800 Subject: [PATCH 21/62] static methods added to help in building objects hashKey based Authentication tokens --- .../authentication/AbstractAuthenticationToken.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java index 4eb602cc6fa..46d08eec30f 100644 --- a/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java @@ -222,4 +222,16 @@ public String toString() { return sb.toString(); } + + protected static Integer extractKeyHash(String key) { + Object value = nullSafeValue(key); + return value.hashCode(); + } + + protected static Object nullSafeValue(Object value){ + if(value == null || "".equals(value)) { + throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); + } + return value; + } } From e8c176ad15285815336bd2b0d9eeded122f974ce Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 15:15:56 +0800 Subject: [PATCH 22/62] Private constructor added in AnonymousAuthenticationToken to enable jackson deserialization support --- .../AnonymousAuthenticationToken.java | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java index 6b191daadc2..fdb94f3a6e2 100644 --- a/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java @@ -18,7 +18,6 @@ import java.io.Serializable; import java.util.Collection; -import java.util.List; import org.springframework.security.core.GrantedAuthority; @@ -50,16 +49,25 @@ public class AnonymousAuthenticationToken extends AbstractAuthenticationToken im */ public AnonymousAuthenticationToken(String key, Object principal, Collection authorities) { + this(extractKeyHash(key), nullSafeValue(principal), authorities); + } + + /** + * Constructor helps in Jackson Deserialization + * + * @param keyHash hashCode of provided Key, constructed by above constructor + * @param principal the principal (typically a UserDetails) + * @param authorities the authorities granted to the principal + */ + private AnonymousAuthenticationToken(Integer keyHash, Object principal, + Collection authorities) { super(authorities); - if ((key == null) || ("".equals(key)) || (principal == null) - || "".equals(principal) || (authorities == null) - || (authorities.isEmpty())) { - throw new IllegalArgumentException( - "Cannot pass null or empty values to constructor"); + if(authorities == null || authorities.isEmpty()) { + throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); } - this.keyHash = key.hashCode(); + this.keyHash = keyHash; this.principal = principal; setAuthenticated(true); } From 5625231ff621351ee204cb50912ca68bf011fbec Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 15:16:44 +0800 Subject: [PATCH 23/62] Jackson and JSONAssert dependencies added in cas module --- cas/cas.gradle | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cas/cas.gradle b/cas/cas.gradle index 9149d794839..eb3e27b2784 100644 --- a/cas/cas.gradle +++ b/cas/cas.gradle @@ -8,7 +8,10 @@ dependencies { "org.springframework:spring-web:$springVersion", "org.jasig.cas.client:cas-client-core:$casClientVersion" - optional "net.sf.ehcache:ehcache:$ehcacheVersion" + optional "net.sf.ehcache:ehcache:$ehcacheVersion", + "com.fasterxml.jackson.core:jackson-databind:$jacksonDatavindVersion" + + testCompile "org.skyscreamer:jsonassert:$jsonassertVersion" provided "javax.servlet:javax.servlet-api:$servletApiVersion" } From 4460f231986e3ad07ed223f751e18020b65a029d Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 15:17:38 +0800 Subject: [PATCH 24/62] Private constructor added to enable jackson deserialization support --- .../CasAuthenticationToken.java | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java index 856781ae5e1..77465484d9a 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java @@ -70,9 +70,35 @@ public CasAuthenticationToken(final String key, final Object principal, final Object credentials, final Collection authorities, final UserDetails userDetails, final Assertion assertion) { + this(extractKeyHash(key), principal, credentials, authorities, userDetails, assertion); + } + + /** + * Private constructor for Jackson Deserialization support + * + * @param keyHash hashCode of provided key to identify if this object made by a given + * {@link CasAuthenticationProvider} + * @param principal typically the UserDetails object (cannot be null) + * @param credentials the service/proxy ticket ID from CAS (cannot be + * null) + * @param authorities the authorities granted to the user (from the + * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot + * be null) + * @param userDetails the user details (from the + * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot + * be null) + * @param assertion the assertion returned from the CAS servers. It contains the + * principal and how to obtain a proxy ticket for the user. + * + * @throws IllegalArgumentException if a null was passed + */ + private CasAuthenticationToken(final Integer keyHash, final Object principal, + final Object credentials, + final Collection authorities, + final UserDetails userDetails, final Assertion assertion) { super(authorities); - if ((key == null) || ("".equals(key)) || (principal == null) + if ((principal == null) || "".equals(principal) || (credentials == null) || "".equals(credentials) || (authorities == null) || (userDetails == null) || (assertion == null)) { @@ -80,7 +106,7 @@ public CasAuthenticationToken(final String key, final Object principal, "Cannot pass null or empty values to constructor"); } - this.keyHash = key.hashCode(); + this.keyHash = keyHash; this.principal = principal; this.credentials = credentials; this.userDetails = userDetails; From d113906c49f13d1437e4fbcc5c295298a406f64a Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 15:18:54 +0800 Subject: [PATCH 25/62] Mixin and tests added for CasAuthenticationToken --- .../jackson2/CasAuthenticationTokenMixin.java | 27 +++++ .../CasAuthenticationTokenMixinTest.java | 112 ++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java create mode 100644 cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java new file mode 100644 index 00000000000..d320007206d --- /dev/null +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java @@ -0,0 +1,27 @@ +package org.springframework.security.cas.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; +import org.jasig.cas.client.validation.Assertion; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; + +/** + * @author Jitendra Singh + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +@JsonIgnoreProperties(ignoreUnknown = true) +public class CasAuthenticationTokenMixin { + + @JsonCreator + public CasAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, + @JsonProperty("credentials") Object credentials, + @JsonProperty("authorities") Collection authorities, + @JsonProperty("userDetails") UserDetails userDetails, @JsonProperty("assertion") Assertion assertion) { + + } +} diff --git a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java new file mode 100644 index 00000000000..e3c09257084 --- /dev/null +++ b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java @@ -0,0 +1,112 @@ +package org.springframework.security.cas.jackson2; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.jasig.cas.client.authentication.AttributePrincipalImpl; +import org.jasig.cas.client.validation.Assertion; +import org.jasig.cas.client.validation.AssertionImpl; +import org.json.JSONException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.security.cas.authentication.CasAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.jackson2.SimpleGrantedAuthorityMixin; +import org.springframework.security.jackson2.UnmodifiableSetMixin; +import org.springframework.security.jackson2.UserMixin; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; + +import static org.assertj.core.api.Assertions.*; + +/** + * @author Jitendra Singh + */ +@RunWith(MockitoJUnitRunner.class) +public class CasAuthenticationTokenMixinTest { + + ObjectMapper buildObjectMapper() { + ObjectMapper mapper = new ObjectMapper() + .enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); + mapper.setVisibilityChecker(mapper.getVisibilityChecker().withVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)); + mapper.addMixIn(CasAuthenticationToken.class, CasAuthenticationTokenMixin.class) + .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) + .addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class) + .addMixIn(User.class, UserMixin.class) + .addMixIn(AssertionImpl.class, AssertionImplMixin.class) + .addMixIn(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class); + return mapper; + } + + @Test(expected = IllegalArgumentException.class) + public void nullKeyTest() { + new CasAuthenticationToken(null, "user", "pass", Collections.emptyList(), + new User("user", "pass", Collections.emptyList()), null); + } + + @Test(expected = IllegalArgumentException.class) + public void blankKeyTest() { + new CasAuthenticationToken("", "user", "pass", Collections.emptyList(), + new User("user", "pass", Collections.emptyList()), null); + } + + @Test + public void serializeCasAuthenticationTest() throws JsonProcessingException, JSONException { + String key = "casKey"; + Date startDate = new Date(); + Date endDate = new Date(); + Collection authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); + Assertion assertion = new AssertionImpl(new AttributePrincipalImpl("assertName"), startDate, endDate, startDate, Collections.emptyMap()); + CasAuthenticationToken token = new CasAuthenticationToken(key, "user", "pass", authorities, + new User("user", "pass", authorities), assertion); + + String expectedJson = "{\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", \"keyHash\": "+key.hashCode()+"," + + "\"principal\": \"user\", \"credentials\": \"pass\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]," + + "\"userDetails\": {\"@class\": \"org.springframework.security.core.userdetails.User\",\"username\": \"user\", \"password\": \"pass\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," + + "\"authenticated\": true, \"details\": null, \"name\": \"user\"," + + "\"assertion\": {" + + "\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", \"principal\": {\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", \"name\": \"assertName\", \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, \"proxyGrantingTicket\": null, \"proxyRetriever\": null}, " + + "\"validFromDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"validUntilDate\": [\"java.util.Date\", "+endDate.getTime()+"]," + + "\"authenticationDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" + + "}}"; + String actualJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } + + @Test + public void deserializeCasAuthenticationTest() throws IOException, JSONException { + String key = "casKey"; + Date startDate = new Date(); + Date endDate = new Date(); + + String expectedJson = "{\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", \"keyHash\": "+key.hashCode()+"," + + "\"principal\": \"user\", \"credentials\": \"pass\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]," + + "\"userDetails\": {\"@class\": \"org.springframework.security.core.userdetails.User\",\"username\": \"user\", \"password\": \"pass\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," + + "\"authenticated\": true, \"details\": null, \"name\": \"user\"," + + "\"assertion\": {" + + "\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", \"principal\": {\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", \"name\": \"assertName\", \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, \"proxyGrantingTicket\": null, \"proxyRetriever\": null}, " + + "\"validFromDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"validUntilDate\": [\"java.util.Date\", "+endDate.getTime()+"]," + + "\"authenticationDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" + + "}}"; + CasAuthenticationToken token = buildObjectMapper().readValue(expectedJson, CasAuthenticationToken.class); + assertThat(token).isNotNull(); + assertThat(token.getUserDetails()).isNotNull().isInstanceOf(User.class); + assertThat(token.getAssertion()).isNotNull().isInstanceOf(AssertionImpl.class); + assertThat(token.getKeyHash()).isEqualTo(key.hashCode()); + assertThat(token.getUserDetails().getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + assertThat(token.getAssertion().getAuthenticationDate()).isEqualTo(startDate); + assertThat(token.getAssertion().getValidFromDate()).isEqualTo(startDate); + assertThat(token.getAssertion().getValidUntilDate()).isEqualTo(endDate); + assertThat(token.getAssertion().getPrincipal().getName()).isEqualTo("assertName"); + assertThat(token.getAssertion().getAttributes()).hasSize(0); + } +} From e867ce53a875f64ee905929a8c268af290135e1d Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 15:21:50 +0800 Subject: [PATCH 26/62] Mix-ins added for AssertionImpl and AttributePrincipalImpl classes used in CasAuthenticationToken jackson deserialization --- .../cas/jackson2/AssertionImplMixin.java | 25 +++++++++++++++++++ .../jackson2/AttributePrincipalImplMixin.java | 21 ++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java create mode 100644 cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java new file mode 100644 index 00000000000..16adc66e4f7 --- /dev/null +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java @@ -0,0 +1,25 @@ +package org.springframework.security.cas.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; +import org.jasig.cas.client.authentication.AttributePrincipal; + +import java.util.Date; +import java.util.Map; + +/** + * @author Jitendra Singh + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +@JsonIgnoreProperties(value = {"valid"}) +public class AssertionImplMixin { + + @JsonCreator + public AssertionImplMixin(@JsonProperty("principal") AttributePrincipal principal, + @JsonProperty("validFromDate") Date validFromDate, @JsonProperty("validUntilDate") Date validUntilDate, + @JsonProperty("authenticationDate") Date authenticationDate, @JsonProperty("attributes") Map attributes){ + + } +} diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java new file mode 100644 index 00000000000..f954a5778a0 --- /dev/null +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java @@ -0,0 +1,21 @@ +package org.springframework.security.cas.jackson2; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import org.jasig.cas.client.proxy.ProxyRetriever; + +import java.util.Map; + +/** + * @author Jitendra Singh + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +public class AttributePrincipalImplMixin { + + @JsonCreator + public AttributePrincipalImplMixin(@JsonProperty("name") String name, @JsonProperty("attributes") Map attributes, + @JsonProperty("proxyGrantingTicket") String proxyGrantingTicket, + @JsonProperty("proxyRetriever") ProxyRetriever proxyRetriever) { + } +} From 9cc1a37f206bce2612d8dd168bc95eb064e189df Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 15:25:42 +0800 Subject: [PATCH 27/62] Mix-in and tests added for AnonymousAuthenticationToken --- .../AnonymousAuthenticationTokenMixin.java | 19 +++++ ...AnonymousAuthenticationTokenMixinTest.java | 74 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java create mode 100644 core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java diff --git a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java new file mode 100644 index 00000000000..cb5a6ccfa9a --- /dev/null +++ b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java @@ -0,0 +1,19 @@ +package org.springframework.security.jackson2; + +import com.fasterxml.jackson.annotation.*; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Collection; + +/** + * @author Jitendra Singh + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +@JsonIgnoreProperties(ignoreUnknown = true) +public class AnonymousAuthenticationTokenMixin { + + @JsonCreator + public AnonymousAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, + @JsonProperty("authorities") Collection authorities) { + } +} diff --git a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java new file mode 100644 index 00000000000..90fef7763c7 --- /dev/null +++ b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java @@ -0,0 +1,74 @@ +package org.springframework.security.jackson2; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.json.JSONException; +import org.junit.Test; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.authentication.RememberMeAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; + +import java.io.IOException; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Jitendra Singh + */ +public class AnonymousAuthenticationTokenMixinTest extends AbstractMixinTests { + + @Override + public ObjectMapper buildObjectMapper() { + return super.buildObjectMapper() + .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) + .addMixIn(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testWithNullAuthorities() throws JsonProcessingException, JSONException { + new AnonymousAuthenticationToken("key", "principal", null); + } + + @Test(expected = IllegalArgumentException.class) + public void testWithEmptyAuthorities() throws JsonProcessingException, JSONException { + new AnonymousAuthenticationToken("key", "principal", Collections.emptyList()); + } + + @Test + public void serializeAnonymousAuthenticationTokenTest() throws JsonProcessingException, JSONException { + String key = "key"; + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+ + "\"principal\": \"user\", \"credentials\": \"\", \"authenticated\": true, \"name\": \"user\", \"keyHash\": "+key.hashCode()+","+ + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + AnonymousAuthenticationToken token = new AnonymousAuthenticationToken( + key, "user", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")) + ); + String actualJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } + + @Test + public void deserializeAnonymousAuthenticationTokenTest() throws IOException { + String key = "123456789"; + String jsonString = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+ + "\"principal\": \"user\", \"credentials\": \"\", \"authenticated\": true, \"name\": \"user\", \"keyHash\": "+key.hashCode()+","+ + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + AnonymousAuthenticationToken token = buildObjectMapper().readValue(jsonString, AnonymousAuthenticationToken.class); + assertThat(token).isNotNull(); + assertThat(token.getKeyHash()).isEqualTo(key.hashCode()); + assertThat(token.getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + } + + @Test(expected = JsonMappingException.class) + public void deserializeAnonymousAuthenticationTokenWithoutAuthoritiesTest() throws IOException { + String key = "123456789"; + String jsonString = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+ + "\"principal\": \"user\", \"credentials\": \"\", \"authenticated\": true, \"name\": \"user\", \"keyHash\": "+key.hashCode()+","+ + "\"authorities\": [\"java.util.ArrayList\", []]}"; + buildObjectMapper().readValue(jsonString, AnonymousAuthenticationToken.class); + } +} From b16da6690384501874b80aee395ab5b7dac45fb6 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 16:48:22 +0800 Subject: [PATCH 28/62] License header added and indentation changed to tab --- .../CasAuthenticationToken.java | 8 +- .../cas/jackson2/AssertionImplMixin.java | 27 ++- .../jackson2/AttributePrincipalImplMixin.java | 26 ++- .../jackson2/CasAuthenticationTokenMixin.java | 29 +++- .../CasAuthenticationTokenMixinTest.java | 154 +++++++++-------- .../AnonymousAuthenticationToken.java | 2 +- .../web/jackson2/CookieDeserializer.java | 50 ++++-- .../security/web/jackson2/CookieMixin.java | 22 ++- .../web/jackson2/DefaultCsrfTokenMixin.java | 40 +++-- .../jackson2/DefaultSavedRequestMixin.java | 22 ++- .../WebAuthenticationDetailsMixin.java | 24 ++- .../web/jackson2/CookieMixinTest.java | 64 ++++--- .../jackson2/DefaultCsrfTokenMixinTests.java | 92 +++++----- .../DefaultSavedRequestMixinTest.java | 158 ++++++++++-------- .../WebAuthenticationDetailsMixinTest.java | 90 ++++++---- 15 files changed, 507 insertions(+), 301 deletions(-) diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java index 77465484d9a..9ac0bf1e2db 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java @@ -91,11 +91,11 @@ public CasAuthenticationToken(final String key, final Object principal, * principal and how to obtain a proxy ticket for the user. * * @throws IllegalArgumentException if a null was passed - */ + */ private CasAuthenticationToken(final Integer keyHash, final Object principal, - final Object credentials, - final Collection authorities, - final UserDetails userDetails, final Assertion assertion) { + final Object credentials, + final Collection authorities, + final UserDetails userDetails, final Assertion assertion) { super(authorities); if ((principal == null) diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java index 16adc66e4f7..661bcfbf4b3 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java @@ -1,3 +1,19 @@ +/* + * 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.cas.jackson2; import com.fasterxml.jackson.annotation.JsonCreator; @@ -16,10 +32,9 @@ @JsonIgnoreProperties(value = {"valid"}) public class AssertionImplMixin { - @JsonCreator - public AssertionImplMixin(@JsonProperty("principal") AttributePrincipal principal, - @JsonProperty("validFromDate") Date validFromDate, @JsonProperty("validUntilDate") Date validUntilDate, - @JsonProperty("authenticationDate") Date authenticationDate, @JsonProperty("attributes") Map attributes){ - - } + @JsonCreator + public AssertionImplMixin(@JsonProperty("principal") AttributePrincipal principal, + @JsonProperty("validFromDate") Date validFromDate, @JsonProperty("validUntilDate") Date validUntilDate, + @JsonProperty("authenticationDate") Date authenticationDate, @JsonProperty("attributes") Map attributes){ + } } diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java index f954a5778a0..e78c97f0f37 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java @@ -1,3 +1,19 @@ +/* + * 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.cas.jackson2; import com.fasterxml.jackson.annotation.JsonCreator; @@ -13,9 +29,9 @@ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) public class AttributePrincipalImplMixin { - @JsonCreator - public AttributePrincipalImplMixin(@JsonProperty("name") String name, @JsonProperty("attributes") Map attributes, - @JsonProperty("proxyGrantingTicket") String proxyGrantingTicket, - @JsonProperty("proxyRetriever") ProxyRetriever proxyRetriever) { - } + @JsonCreator + public AttributePrincipalImplMixin(@JsonProperty("name") String name, @JsonProperty("attributes") Map attributes, + @JsonProperty("proxyGrantingTicket") String proxyGrantingTicket, + @JsonProperty("proxyRetriever") ProxyRetriever proxyRetriever) { + } } diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java index d320007206d..a91c686d712 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java @@ -1,3 +1,19 @@ +/* + * 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.cas.jackson2; import com.fasterxml.jackson.annotation.JsonCreator; @@ -17,11 +33,10 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class CasAuthenticationTokenMixin { - @JsonCreator - public CasAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, - @JsonProperty("credentials") Object credentials, - @JsonProperty("authorities") Collection authorities, - @JsonProperty("userDetails") UserDetails userDetails, @JsonProperty("assertion") Assertion assertion) { - - } + @JsonCreator + public CasAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, + @JsonProperty("credentials") Object credentials, + @JsonProperty("authorities") Collection authorities, + @JsonProperty("userDetails") UserDetails userDetails, @JsonProperty("assertion") Assertion assertion) { + } } diff --git a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java index e3c09257084..02a81cb2048 100644 --- a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java +++ b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java @@ -1,3 +1,19 @@ +/* + * 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.cas.jackson2; import com.fasterxml.jackson.annotation.JsonAutoDetect; @@ -34,79 +50,79 @@ @RunWith(MockitoJUnitRunner.class) public class CasAuthenticationTokenMixinTest { - ObjectMapper buildObjectMapper() { - ObjectMapper mapper = new ObjectMapper() - .enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); - mapper.setVisibilityChecker(mapper.getVisibilityChecker().withVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)); - mapper.addMixIn(CasAuthenticationToken.class, CasAuthenticationTokenMixin.class) - .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) - .addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class) - .addMixIn(User.class, UserMixin.class) - .addMixIn(AssertionImpl.class, AssertionImplMixin.class) - .addMixIn(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class); - return mapper; - } + ObjectMapper buildObjectMapper() { + ObjectMapper mapper = new ObjectMapper() + .enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); + mapper.setVisibilityChecker(mapper.getVisibilityChecker().withVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)); + mapper.addMixIn(CasAuthenticationToken.class, CasAuthenticationTokenMixin.class) + .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) + .addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class) + .addMixIn(User.class, UserMixin.class) + .addMixIn(AssertionImpl.class, AssertionImplMixin.class) + .addMixIn(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class); + return mapper; + } - @Test(expected = IllegalArgumentException.class) - public void nullKeyTest() { - new CasAuthenticationToken(null, "user", "pass", Collections.emptyList(), - new User("user", "pass", Collections.emptyList()), null); - } + @Test(expected = IllegalArgumentException.class) + public void nullKeyTest() { + new CasAuthenticationToken(null, "user", "pass", Collections.emptyList(), + new User("user", "pass", Collections.emptyList()), null); + } - @Test(expected = IllegalArgumentException.class) - public void blankKeyTest() { - new CasAuthenticationToken("", "user", "pass", Collections.emptyList(), - new User("user", "pass", Collections.emptyList()), null); - } + @Test(expected = IllegalArgumentException.class) + public void blankKeyTest() { + new CasAuthenticationToken("", "user", "pass", Collections.emptyList(), + new User("user", "pass", Collections.emptyList()), null); + } - @Test - public void serializeCasAuthenticationTest() throws JsonProcessingException, JSONException { - String key = "casKey"; - Date startDate = new Date(); - Date endDate = new Date(); - Collection authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); - Assertion assertion = new AssertionImpl(new AttributePrincipalImpl("assertName"), startDate, endDate, startDate, Collections.emptyMap()); - CasAuthenticationToken token = new CasAuthenticationToken(key, "user", "pass", authorities, - new User("user", "pass", authorities), assertion); + @Test + public void serializeCasAuthenticationTest() throws JsonProcessingException, JSONException { + String key = "casKey"; + Date startDate = new Date(); + Date endDate = new Date(); + Collection authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); + Assertion assertion = new AssertionImpl(new AttributePrincipalImpl("assertName"), startDate, endDate, startDate, Collections.emptyMap()); + CasAuthenticationToken token = new CasAuthenticationToken(key, "user", "pass", authorities, + new User("user", "pass", authorities), assertion); - String expectedJson = "{\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", \"keyHash\": "+key.hashCode()+"," + - "\"principal\": \"user\", \"credentials\": \"pass\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]," + - "\"userDetails\": {\"@class\": \"org.springframework.security.core.userdetails.User\",\"username\": \"user\", \"password\": \"pass\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," + - "\"authenticated\": true, \"details\": null, \"name\": \"user\"," + - "\"assertion\": {" + - "\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", \"principal\": {\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", \"name\": \"assertName\", \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, \"proxyGrantingTicket\": null, \"proxyRetriever\": null}, " + - "\"validFromDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"validUntilDate\": [\"java.util.Date\", "+endDate.getTime()+"]," + - "\"authenticationDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" + - "}}"; - String actualJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, actualJson, true); - } + String expectedJson = "{\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", \"keyHash\": "+key.hashCode()+"," + + "\"principal\": \"user\", \"credentials\": \"pass\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]," + + "\"userDetails\": {\"@class\": \"org.springframework.security.core.userdetails.User\",\"username\": \"user\", \"password\": \"pass\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," + + "\"authenticated\": true, \"details\": null, \"name\": \"user\"," + + "\"assertion\": {" + + "\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", \"principal\": {\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", \"name\": \"assertName\", \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, \"proxyGrantingTicket\": null, \"proxyRetriever\": null}, " + + "\"validFromDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"validUntilDate\": [\"java.util.Date\", "+endDate.getTime()+"]," + + "\"authenticationDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" + + "}}"; + String actualJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } - @Test - public void deserializeCasAuthenticationTest() throws IOException, JSONException { - String key = "casKey"; - Date startDate = new Date(); - Date endDate = new Date(); + @Test + public void deserializeCasAuthenticationTest() throws IOException, JSONException { + String key = "casKey"; + Date startDate = new Date(); + Date endDate = new Date(); - String expectedJson = "{\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", \"keyHash\": "+key.hashCode()+"," + - "\"principal\": \"user\", \"credentials\": \"pass\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]," + - "\"userDetails\": {\"@class\": \"org.springframework.security.core.userdetails.User\",\"username\": \"user\", \"password\": \"pass\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," + - "\"authenticated\": true, \"details\": null, \"name\": \"user\"," + - "\"assertion\": {" + - "\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", \"principal\": {\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", \"name\": \"assertName\", \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, \"proxyGrantingTicket\": null, \"proxyRetriever\": null}, " + - "\"validFromDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"validUntilDate\": [\"java.util.Date\", "+endDate.getTime()+"]," + - "\"authenticationDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" + - "}}"; - CasAuthenticationToken token = buildObjectMapper().readValue(expectedJson, CasAuthenticationToken.class); - assertThat(token).isNotNull(); - assertThat(token.getUserDetails()).isNotNull().isInstanceOf(User.class); - assertThat(token.getAssertion()).isNotNull().isInstanceOf(AssertionImpl.class); - assertThat(token.getKeyHash()).isEqualTo(key.hashCode()); - assertThat(token.getUserDetails().getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); - assertThat(token.getAssertion().getAuthenticationDate()).isEqualTo(startDate); - assertThat(token.getAssertion().getValidFromDate()).isEqualTo(startDate); - assertThat(token.getAssertion().getValidUntilDate()).isEqualTo(endDate); - assertThat(token.getAssertion().getPrincipal().getName()).isEqualTo("assertName"); - assertThat(token.getAssertion().getAttributes()).hasSize(0); - } + String expectedJson = "{\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", \"keyHash\": "+key.hashCode()+"," + + "\"principal\": \"user\", \"credentials\": \"pass\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]," + + "\"userDetails\": {\"@class\": \"org.springframework.security.core.userdetails.User\",\"username\": \"user\", \"password\": \"pass\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," + + "\"authenticated\": true, \"details\": null, \"name\": \"user\"," + + "\"assertion\": {" + + "\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", \"principal\": {\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", \"name\": \"assertName\", \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, \"proxyGrantingTicket\": null, \"proxyRetriever\": null}, " + + "\"validFromDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"validUntilDate\": [\"java.util.Date\", "+endDate.getTime()+"]," + + "\"authenticationDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" + + "}}"; + CasAuthenticationToken token = buildObjectMapper().readValue(expectedJson, CasAuthenticationToken.class); + assertThat(token).isNotNull(); + assertThat(token.getUserDetails()).isNotNull().isInstanceOf(User.class); + assertThat(token.getAssertion()).isNotNull().isInstanceOf(AssertionImpl.class); + assertThat(token.getKeyHash()).isEqualTo(key.hashCode()); + assertThat(token.getUserDetails().getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + assertThat(token.getAssertion().getAuthenticationDate()).isEqualTo(startDate); + assertThat(token.getAssertion().getValidFromDate()).isEqualTo(startDate); + assertThat(token.getAssertion().getValidUntilDate()).isEqualTo(endDate); + assertThat(token.getAssertion().getPrincipal().getName()).isEqualTo("assertName"); + assertThat(token.getAssertion().getAttributes()).hasSize(0); + } } diff --git a/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java index fdb94f3a6e2..acdbf03c0d2 100644 --- a/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java @@ -60,7 +60,7 @@ public AnonymousAuthenticationToken(String key, Object principal, * @param authorities the authorities granted to the principal */ private AnonymousAuthenticationToken(Integer keyHash, Object principal, - Collection authorities) { + Collection authorities) { super(authorities); if(authorities == null || authorities.isEmpty()) { diff --git a/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java b/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java index c2f35b20b2e..86d7712ae8c 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.core.JsonParser; @@ -17,22 +33,22 @@ */ public 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, "isHttpOnly").asBoolean()); - return cookie; - } + @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, "isHttpOnly").asBoolean()); + return cookie; + } - private JsonNode readJsonNode(JsonNode jsonNode, String field) { - return jsonNode.has(field) && !(jsonNode.get(field) instanceof NullNode) ? jsonNode.get(field) : MissingNode.getInstance(); - } + private JsonNode readJsonNode(JsonNode jsonNode, String field) { + return jsonNode.has(field) && !(jsonNode.get(field) instanceof NullNode) ? jsonNode.get(field) : MissingNode.getInstance(); + } } diff --git a/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java index 7c1f6c36837..8381eac8535 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.JsonAutoDetect; @@ -14,7 +30,7 @@ @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE) public abstract class CookieMixin { - @JsonCreator - public CookieMixin(@JsonProperty("name") String name, @JsonProperty("value") String value) { - } + @JsonCreator + public CookieMixin(@JsonProperty("name") String name, @JsonProperty("value") String value) { + } } diff --git a/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java index 37c7a9dbf43..8e475326622 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.*; @@ -11,16 +27,16 @@ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") public class DefaultCsrfTokenMixin { - /** - * JsonCreator constructor needed by Jackson to create {@link org.springframework.security.web.csrf.DefaultCsrfToken} - * object. - * - * @param headerName - * @param parameterName - * @param token - */ - @JsonCreator - public DefaultCsrfTokenMixin(@JsonProperty("headerName") String headerName, - @JsonProperty("parameterName") String parameterName, @JsonProperty("token") String token) { - } + /** + * JsonCreator constructor needed by Jackson to create {@link org.springframework.security.web.csrf.DefaultCsrfToken} + * object. + * + * @param headerName + * @param parameterName + * @param token + */ + @JsonCreator + public DefaultCsrfTokenMixin(@JsonProperty("headerName") String headerName, + @JsonProperty("parameterName") String parameterName, @JsonProperty("token") String token) { + } } diff --git a/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java index 53cb21b2b6c..08f7902221e 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.JsonAutoDetect; @@ -16,10 +32,10 @@ @JsonDeserialize(builder = DefaultSavedRequest.Builder.class) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY) @JsonIgnoreProperties( - value = {"headerNames", "headerValues", "parameterNames", "redirectUrl"} + value = {"headerNames", "headerValues", "parameterNames", "redirectUrl"} ) public abstract class DefaultSavedRequestMixin { - @JsonProperty("parameters") - public abstract Map getParameterMap(); + @JsonProperty("parameters") + public abstract Map getParameterMap(); } diff --git a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java index 1ea8bf0f7c4..7e3cb824299 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.JsonCreator; @@ -10,8 +26,8 @@ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) public class WebAuthenticationDetailsMixin { - @JsonCreator - WebAuthenticationDetailsMixin(@JsonProperty("remoteAddress") String remoteAddress, - @JsonProperty("sessionId") String sessionId) { - } + @JsonCreator + WebAuthenticationDetailsMixin(@JsonProperty("remoteAddress") String remoteAddress, + @JsonProperty("sessionId") String sessionId) { + } } diff --git a/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java index 8e89612ec8b..b2ecac5190d 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.core.JsonProcessingException; @@ -16,28 +32,28 @@ */ public class CookieMixinTest { - ObjectMapper buildObjectMapper() { - return new ObjectMapper() - .addMixIn(Cookie.class, CookieMixin.class); - } - - @Test - public void serializeCookie() throws JsonProcessingException, JSONException { - Cookie cookie = new Cookie("demo", "cookie1"); - String expectedString = "{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"demo\", \"value\": \"cookie1\"," + - "\"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\": false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}"; - String actualString = buildObjectMapper().writeValueAsString(cookie); - JSONAssert.assertEquals(expectedString, actualString, true); - } - - @Test - public void deserializeCookie() throws IOException { - String cookieString = "{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"demo\", \"value\": \"cookie1\"," + - "\"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\": false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}"; - Cookie cookie = buildObjectMapper().readValue(cookieString, Cookie.class); - assertThat(cookie).isNotNull(); - assertThat(cookie.getName()).isEqualTo("demo"); - assertThat(cookie.getDomain()).isEqualTo(""); - assertThat(cookie.isHttpOnly()).isEqualTo(false); - } + ObjectMapper buildObjectMapper() { + return new ObjectMapper() + .addMixIn(Cookie.class, CookieMixin.class); + } + + @Test + public void serializeCookie() throws JsonProcessingException, JSONException { + Cookie cookie = new Cookie("demo", "cookie1"); + String expectedString = "{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"demo\", \"value\": \"cookie1\"," + + "\"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\": false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}"; + String actualString = buildObjectMapper().writeValueAsString(cookie); + JSONAssert.assertEquals(expectedString, actualString, true); + } + + @Test + public void deserializeCookie() throws IOException { + String cookieString = "{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"demo\", \"value\": \"cookie1\"," + + "\"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\": false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}"; + Cookie cookie = buildObjectMapper().readValue(cookieString, Cookie.class); + assertThat(cookie).isNotNull(); + assertThat(cookie.getName()).isEqualTo("demo"); + assertThat(cookie.getDomain()).isEqualTo(""); + assertThat(cookie.isHttpOnly()).isEqualTo(false); + } } diff --git a/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java index bcd5967cc77..a6c10ed53bc 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.core.JsonProcessingException; @@ -21,42 +37,42 @@ @RunWith(MockitoJUnitRunner.class) public class DefaultCsrfTokenMixinTests { - ObjectMapper objectMapper; - String defaultCsrfTokenJson; - - @Before - public void setup() { - objectMapper = new ObjectMapper(); - objectMapper.addMixIn(DefaultCsrfToken.class, DefaultCsrfTokenMixin.class); - defaultCsrfTokenJson = "{\"@class\": \"org.springframework.security.web.csrf.DefaultCsrfToken\", " + - "\"headerName\": \"csrf-header\", \"parameterName\": \"_csrf\", \"token\": \"1\"}"; - } - - @Test - public void defaultCsrfTokenSerializedTest() throws JsonProcessingException, JSONException { - DefaultCsrfToken token = new DefaultCsrfToken("csrf-header", "_csrf", "1"); - String serializedJson = objectMapper.writeValueAsString(token); - JSONAssert.assertEquals(defaultCsrfTokenJson, serializedJson, true); - } - - @Test - public void defaultCsrfTokenDeserializeTest() throws IOException { - DefaultCsrfToken token = objectMapper.readValue(defaultCsrfTokenJson, 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\"}"; - objectMapper.readValue(tokenJson, DefaultCsrfToken.class); - } - - @Test(expected = JsonMappingException.class) - public void defaultCsrfTokenDeserializeNullValuesTest() throws IOException { - String tokenJson = "{\"@class\": \"org.springframework.security.web.csrf.DefaultCsrfToken\", \"headerName\": \"\", \"parameterName\": null, \"token\": \"1\"}"; - objectMapper.readValue(tokenJson, DefaultCsrfToken.class); - } + ObjectMapper objectMapper; + String defaultCsrfTokenJson; + + @Before + public void setup() { + objectMapper = new ObjectMapper(); + objectMapper.addMixIn(DefaultCsrfToken.class, DefaultCsrfTokenMixin.class); + defaultCsrfTokenJson = "{\"@class\": \"org.springframework.security.web.csrf.DefaultCsrfToken\", " + + "\"headerName\": \"csrf-header\", \"parameterName\": \"_csrf\", \"token\": \"1\"}"; + } + + @Test + public void defaultCsrfTokenSerializedTest() throws JsonProcessingException, JSONException { + DefaultCsrfToken token = new DefaultCsrfToken("csrf-header", "_csrf", "1"); + String serializedJson = objectMapper.writeValueAsString(token); + JSONAssert.assertEquals(defaultCsrfTokenJson, serializedJson, true); + } + + @Test + public void defaultCsrfTokenDeserializeTest() throws IOException { + DefaultCsrfToken token = objectMapper.readValue(defaultCsrfTokenJson, 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\"}"; + objectMapper.readValue(tokenJson, DefaultCsrfToken.class); + } + + @Test(expected = JsonMappingException.class) + public void defaultCsrfTokenDeserializeNullValuesTest() throws IOException { + String tokenJson = "{\"@class\": \"org.springframework.security.web.csrf.DefaultCsrfToken\", \"headerName\": \"\", \"parameterName\": null, \"token\": \"1\"}"; + objectMapper.readValue(tokenJson, DefaultCsrfToken.class); + } } diff --git a/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java index bbfbe399e64..875a310078a 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.JsonAutoDetect; @@ -26,82 +42,82 @@ @RunWith(MockitoJUnitRunner.class) public class DefaultSavedRequestMixinTest { - ObjectMapper buildObjectMapper() { - ObjectMapper mapper = new ObjectMapper() - .enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY) - .addMixIn(DefaultSavedRequest.class, DefaultSavedRequestMixin.class) - .addMixIn(Cookie.class, CookieMixin.class); - mapper.setVisibilityChecker( - mapper.getVisibilityChecker() - .withVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) - .withVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY) - ); - return mapper; - } + ObjectMapper buildObjectMapper() { + ObjectMapper mapper = new ObjectMapper() + .enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY) + .addMixIn(DefaultSavedRequest.class, DefaultSavedRequestMixin.class) + .addMixIn(Cookie.class, CookieMixin.class); + mapper.setVisibilityChecker( + mapper.getVisibilityChecker() + .withVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) + .withVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY) + ); + return mapper; + } - @Test - public void matchRequestBuildWithConstructorAndBuilder() { - DefaultSavedRequest request = new DefaultSavedRequest.Builder() - .setCookies(Collections.singletonList(new Cookie("SESSION", "123456789"))) - .setHeaders(Collections.singletonMap("x-auth-token", Collections.singletonList("12"))) - .setScheme("http").setRequestURL("http://localhost").setServerName("localhost").setRequestURI("") - .setLocales(Collections.singletonList(new Locale("en"))).setContextPath("").setMethod("") - .setServletPath("").build(); - MockHttpServletRequest mockRequest = new MockHttpServletRequest(); - mockRequest.setCookies(new Cookie("SESSION", "123456789")); - mockRequest.addHeader("x-auth-token", "12"); + @Test + public void matchRequestBuildWithConstructorAndBuilder() { + DefaultSavedRequest request = new DefaultSavedRequest.Builder() + .setCookies(Collections.singletonList(new Cookie("SESSION", "123456789"))) + .setHeaders(Collections.singletonMap("x-auth-token", Collections.singletonList("12"))) + .setScheme("http").setRequestURL("http://localhost").setServerName("localhost").setRequestURI("") + .setLocales(Collections.singletonList(new Locale("en"))).setContextPath("").setMethod("") + .setServletPath("").build(); + MockHttpServletRequest mockRequest = new MockHttpServletRequest(); + mockRequest.setCookies(new Cookie("SESSION", "123456789")); + mockRequest.addHeader("x-auth-token", "12"); - assert request.doesRequestMatch(mockRequest, new PortResolverImpl()); - } + assert request.doesRequestMatch(mockRequest, new PortResolverImpl()); + } - @Test - public void serializeDefaultRequestBuildWithConstructorTest() throws IOException, JSONException { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setCookies(new Cookie("SESSION", "123456789")); - request.addHeader("x-auth-token", "12"); + @Test + public void serializeDefaultRequestBuildWithConstructorTest() throws IOException, JSONException { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setCookies(new Cookie("SESSION", "123456789")); + request.addHeader("x-auth-token", "12"); - String expectedJsonString = "{" + - "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}]]," + - "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + - "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + - "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ - "}"; - String actualString = buildObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(new DefaultSavedRequest(request, new PortResolverImpl())); - JSONAssert.assertEquals(expectedJsonString, actualString, true); - } + String expectedJsonString = "{" + + "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}]]," + + "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + + "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + + "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ + "}"; + String actualString = buildObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(new DefaultSavedRequest(request, new PortResolverImpl())); + JSONAssert.assertEquals(expectedJsonString, actualString, true); + } - @Test - public void serializeDefaultRequestBuildWithBuilderTest() throws IOException, JSONException { - DefaultSavedRequest request = new DefaultSavedRequest.Builder() - .setCookies(Collections.singletonList(new Cookie("SESSION", "123456789"))) - .setHeaders(Collections.singletonMap("x-auth-token", Collections.singletonList("12"))) - .setScheme("http").setRequestURL("http://localhost").setServerName("localhost").setRequestURI("") - .setLocales(Collections.singletonList(new Locale("en"))).setContextPath("").setMethod("") - .setServletPath("").build(); + @Test + public void serializeDefaultRequestBuildWithBuilderTest() throws IOException, JSONException { + DefaultSavedRequest request = new DefaultSavedRequest.Builder() + .setCookies(Collections.singletonList(new Cookie("SESSION", "123456789"))) + .setHeaders(Collections.singletonMap("x-auth-token", Collections.singletonList("12"))) + .setScheme("http").setRequestURL("http://localhost").setServerName("localhost").setRequestURI("") + .setLocales(Collections.singletonList(new Locale("en"))).setContextPath("").setMethod("") + .setServletPath("").build(); - String expectedJsonString = "{" + - "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}]]," + - "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + - "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + - "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ - "}"; - String actualString = buildObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(request); - JSONAssert.assertEquals(expectedJsonString, actualString, true); - } + String expectedJsonString = "{" + + "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}]]," + + "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + + "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + + "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ + "}"; + String actualString = buildObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(request); + JSONAssert.assertEquals(expectedJsonString, actualString, true); + } - @Test - public void deserializeDefaultSavedRequest() throws IOException { - String jsonString = "{" + - "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}]]," + - "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + - "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + - "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ - "}"; - DefaultSavedRequest request = buildObjectMapper().readValue(jsonString, DefaultSavedRequest.class); - assertThat(request).isNotNull(); - assertThat(request.getCookies()).hasSize(1); - assertThat(request.getLocales()).hasSize(1).contains(new Locale("en")); - assertThat(request.getHeaderNames()).hasSize(1).contains("x-auth-token"); - assertThat(request.getHeaderValues("x-auth-token")).hasSize(1).contains("12"); - } + @Test + public void deserializeDefaultSavedRequest() throws IOException { + String jsonString = "{" + + "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}]]," + + "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + + "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + + "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ + "}"; + DefaultSavedRequest request = buildObjectMapper().readValue(jsonString, DefaultSavedRequest.class); + assertThat(request).isNotNull(); + assertThat(request.getCookies()).hasSize(1); + assertThat(request.getLocales()).hasSize(1).contains(new Locale("en")); + assertThat(request.getHeaderNames()).hasSize(1).contains("x-auth-token"); + assertThat(request.getHeaderValues("x-auth-token")).hasSize(1).contains("12"); + } } diff --git a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java index b367cc9983e..b54878828e2 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.core.JsonProcessingException; @@ -22,46 +38,46 @@ @RunWith(MockitoJUnitRunner.class) public class WebAuthenticationDetailsMixinTest { - ObjectMapper mapper; + ObjectMapper mapper; - @Before - public void setup() { - mapper = new ObjectMapper() - .addMixIn(WebAuthenticationDetails.class, WebAuthenticationDetailsMixin.class); - } + @Before + public void setup() { + mapper = new ObjectMapper() + .addMixIn(WebAuthenticationDetails.class, WebAuthenticationDetailsMixin.class); + } - @Test - public void buildWebAuthenticationDetailsUsingDifferentConstructors() throws IOException { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setRemoteAddr("localhost"); - request.setSession(new MockHttpSession(null, "1")); + @Test + public void buildWebAuthenticationDetailsUsingDifferentConstructors() throws IOException { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setRemoteAddr("localhost"); + request.setSession(new MockHttpSession(null, "1")); - WebAuthenticationDetails details = new WebAuthenticationDetails(request); - String jsonString = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + - "\"sessionId\": \"1\", \"remoteAddress\": \"/localhost\"}"; - WebAuthenticationDetails authenticationDetails = mapper.readValue(jsonString, WebAuthenticationDetails.class); - assertThat(details.equals(authenticationDetails)); - } + WebAuthenticationDetails details = new WebAuthenticationDetails(request); + String jsonString = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + + "\"sessionId\": \"1\", \"remoteAddress\": \"/localhost\"}"; + WebAuthenticationDetails authenticationDetails = mapper.readValue(jsonString, WebAuthenticationDetails.class); + assertThat(details.equals(authenticationDetails)); + } - @Test - public void webAuthenticationDetailsSerializeTest() throws JsonProcessingException, JSONException { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setRemoteAddr("/home"); - request.setSession(new MockHttpSession(null, "1")); - WebAuthenticationDetails details = new WebAuthenticationDetails(request); - String expectedJson = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + - "\"sessionId\": \"1\", \"remoteAddress\": \"/home\"}"; - String actualJson = mapper.writeValueAsString(details); - JSONAssert.assertEquals(expectedJson, actualJson, true); - } + @Test + public void webAuthenticationDetailsSerializeTest() throws JsonProcessingException, JSONException { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setRemoteAddr("/home"); + request.setSession(new MockHttpSession(null, "1")); + WebAuthenticationDetails details = new WebAuthenticationDetails(request); + String expectedJson = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + + "\"sessionId\": \"1\", \"remoteAddress\": \"/home\"}"; + String actualJson = mapper.writeValueAsString(details); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } - @Test - public void webAuthenticationDetailsDeserializeTest() throws IOException, JSONException { - String actualJson = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + - "\"sessionId\": \"1\", \"remoteAddress\": \"/home\"}"; - WebAuthenticationDetails details = mapper.readValue(actualJson, WebAuthenticationDetails.class); - assertThat(details).isNotNull(); - assertThat(details.getRemoteAddress()).isEqualTo("/home"); - assertThat(details.getSessionId()).isEqualTo("1"); - } + @Test + public void webAuthenticationDetailsDeserializeTest() throws IOException, JSONException { + String actualJson = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + + "\"sessionId\": \"1\", \"remoteAddress\": \"/home\"}"; + WebAuthenticationDetails details = mapper.readValue(actualJson, WebAuthenticationDetails.class); + assertThat(details).isNotNull(); + assertThat(details.getRemoteAddress()).isEqualTo("/home"); + assertThat(details.getSessionId()).isEqualTo("1"); + } } From 26d4e260c1c54f34b273bd7aa4313827c6d9e61e Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 17:10:42 +0800 Subject: [PATCH 29/62] License header added and indentation changed to tab --- .../RememberMeAuthenticationToken.java | 2 +- .../AnonymousAuthenticationTokenMixin.java | 24 ++- .../RememberMeAuthenticationTokenMixin.java | 26 ++- .../jackson2/SimpleGrantedAuthorityMixin.java | 26 ++- .../jackson2/UnmodifiableSetMixin.java | 20 ++- .../security/jackson2/UserDeserializer.java | 48 +++-- .../security/jackson2/UserMixin.java | 26 ++- ...sswordAuthenticationTokenDeserializer.java | 72 +++++--- ...rnamePasswordAuthenticationTokenMixin.java | 16 ++ .../security/jackson2/AbstractMixinTests.java | 28 ++- ...AnonymousAuthenticationTokenMixinTest.java | 106 ++++++----- ...ememberMeAuthenticationTokenMixinTest.java | 142 ++++++++------- .../jackson2/SecurityContextMixinTest.java | 90 ++++++---- .../SimpleGrantedAuthorityMixinTest.java | 74 +++++--- .../jackson2/UserDeserializerTests.java | 144 ++++++++------- ...ePasswordAuthenticationTokenMixinTest.java | 168 ++++++++++-------- 16 files changed, 626 insertions(+), 386 deletions(-) diff --git a/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java index de0fc50beb5..50d086963ed 100644 --- a/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java @@ -73,7 +73,7 @@ public RememberMeAuthenticationToken(String key, Object principal, * @param keyHash hashCode of above given key. * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal - */ + */ private RememberMeAuthenticationToken(Integer keyHash, Object principal, Collection authorities) { super(authorities); diff --git a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java index cb5a6ccfa9a..1bb66328880 100644 --- a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.*; @@ -12,8 +28,8 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class AnonymousAuthenticationTokenMixin { - @JsonCreator - public AnonymousAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, - @JsonProperty("authorities") Collection authorities) { - } + @JsonCreator + public AnonymousAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, + @JsonProperty("authorities") Collection authorities) { + } } diff --git a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java index b69cfb4984a..2be534fbe59 100644 --- a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.JsonCreator; @@ -15,9 +31,9 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class RememberMeAuthenticationTokenMixin { - @JsonCreator - public RememberMeAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, - @JsonProperty("principal") Object principal, - @JsonProperty("authorities") Collection authorities) { - } + @JsonCreator + public RememberMeAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, + @JsonProperty("principal") Object principal, + @JsonProperty("authorities") Collection authorities) { + } } diff --git a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java index 22d3a6a2d8a..2dd80db4291 100644 --- a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.*; @@ -13,10 +29,10 @@ @JsonIgnoreProperties(ignoreUnknown = true) public abstract class SimpleGrantedAuthorityMixin { - @JsonCreator - public SimpleGrantedAuthorityMixin(@JsonProperty("role") String role) { - } + @JsonCreator + public SimpleGrantedAuthorityMixin(@JsonProperty("role") String role) { + } - @JsonProperty("role") - public abstract String getAuthority(); + @JsonProperty("role") + public abstract String getAuthority(); } diff --git a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java index ef7347ec7d0..5b41708222a 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.JsonCreator; @@ -11,6 +27,6 @@ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) public class UnmodifiableSetMixin { - @JsonCreator - UnmodifiableSetMixin(Set s) {} + @JsonCreator + UnmodifiableSetMixin(Set s) {} } diff --git a/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java b/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java index b6728d1b9db..f8533ecb436 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java +++ b/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.core.JsonParser; @@ -20,21 +36,21 @@ */ public class UserDeserializer extends JsonDeserializer { - @Override - public User deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { - ObjectMapper mapper = (ObjectMapper) jp.getCodec(); - JsonNode jsonNode = mapper.readTree(jp); - Set authorities = mapper.convertValue(jsonNode.get("authorities"), new TypeReference>() { - }); - return new User( - readJsonNode(jsonNode, "username").asText(), readJsonNode(jsonNode, "password").asText(""), - readJsonNode(jsonNode, "enabled").asBoolean(), readJsonNode(jsonNode, "accountNonExpired").asBoolean(), - readJsonNode(jsonNode, "credentialsNonExpired").asBoolean(), - readJsonNode(jsonNode, "accountNonLocked").asBoolean(), authorities - ); - } + @Override + public User deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + ObjectMapper mapper = (ObjectMapper) jp.getCodec(); + JsonNode jsonNode = mapper.readTree(jp); + Set authorities = mapper.convertValue(jsonNode.get("authorities"), new TypeReference>() { + }); + return new User( + readJsonNode(jsonNode, "username").asText(), readJsonNode(jsonNode, "password").asText(""), + readJsonNode(jsonNode, "enabled").asBoolean(), readJsonNode(jsonNode, "accountNonExpired").asBoolean(), + readJsonNode(jsonNode, "credentialsNonExpired").asBoolean(), + readJsonNode(jsonNode, "accountNonLocked").asBoolean(), authorities + ); + } - private JsonNode readJsonNode(JsonNode jsonNode, String field) { - return jsonNode.has(field) ? jsonNode.get(field) : MissingNode.getInstance(); - } + private JsonNode readJsonNode(JsonNode jsonNode, String field) { + return jsonNode.has(field) ? jsonNode.get(field) : MissingNode.getInstance(); + } } diff --git a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java index e805cd8bdc4..17b15a7d840 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.JsonProperty; @@ -14,9 +30,9 @@ @JsonDeserialize(using = UserDeserializer.class) public abstract class UserMixin { - public UserMixin(@JsonProperty("username") String username, @JsonProperty("password") String password, - @JsonProperty("enabled") boolean enabled, @JsonProperty("accountNonExpired") boolean accountNonExpired, - @JsonProperty("credentialsNonExpired") boolean credentialsNonExpired, - @JsonProperty("accountNonLocked") boolean accountNonLocked, @JsonProperty("authorities") Collection authorities) { - } + public UserMixin(@JsonProperty("username") String username, @JsonProperty("password") String password, + @JsonProperty("enabled") boolean enabled, @JsonProperty("accountNonExpired") boolean accountNonExpired, + @JsonProperty("credentialsNonExpired") boolean credentialsNonExpired, + @JsonProperty("accountNonLocked") boolean accountNonLocked, @JsonProperty("authorities") Collection authorities) { + } } diff --git a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java index 52e00ed7ab2..8ef3e1aaf20 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java +++ b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.core.JsonParser; @@ -20,33 +36,33 @@ */ public class UsernamePasswordAuthenticationTokenDeserializer extends JsonDeserializer { - @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; - } + @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(); - } + private JsonNode readJsonNode(JsonNode jsonNode, String field) { + return jsonNode.has(field) ? jsonNode.get(field) : MissingNode.getInstance(); + } } diff --git a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java index 5b531177b49..a0b375a2022 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.*; diff --git a/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java index 5c2f63c95a5..c1023061329 100644 --- a/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.JsonAutoDetect; @@ -13,10 +29,10 @@ @RunWith(MockitoJUnitRunner.class) public abstract class AbstractMixinTests { - protected ObjectMapper buildObjectMapper() { - ObjectMapper mapper = new ObjectMapper() - .enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); - mapper.setVisibilityChecker(mapper.getVisibilityChecker().withVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)); - return mapper; - } + protected ObjectMapper buildObjectMapper() { + ObjectMapper mapper = new ObjectMapper() + .enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); + mapper.setVisibilityChecker(mapper.getVisibilityChecker().withVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)); + return mapper; + } } diff --git a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java index 90fef7763c7..434c30bb1d3 100644 --- a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.core.JsonProcessingException; @@ -21,54 +37,54 @@ */ public class AnonymousAuthenticationTokenMixinTest extends AbstractMixinTests { - @Override - public ObjectMapper buildObjectMapper() { - return super.buildObjectMapper() - .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) - .addMixIn(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class); - } + @Override + public ObjectMapper buildObjectMapper() { + return super.buildObjectMapper() + .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) + .addMixIn(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class); + } - @Test(expected = IllegalArgumentException.class) - public void testWithNullAuthorities() throws JsonProcessingException, JSONException { - new AnonymousAuthenticationToken("key", "principal", null); - } + @Test(expected = IllegalArgumentException.class) + public void testWithNullAuthorities() throws JsonProcessingException, JSONException { + new AnonymousAuthenticationToken("key", "principal", null); + } - @Test(expected = IllegalArgumentException.class) - public void testWithEmptyAuthorities() throws JsonProcessingException, JSONException { - new AnonymousAuthenticationToken("key", "principal", Collections.emptyList()); - } + @Test(expected = IllegalArgumentException.class) + public void testWithEmptyAuthorities() throws JsonProcessingException, JSONException { + new AnonymousAuthenticationToken("key", "principal", Collections.emptyList()); + } - @Test - public void serializeAnonymousAuthenticationTokenTest() throws JsonProcessingException, JSONException { - String key = "key"; - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+ - "\"principal\": \"user\", \"credentials\": \"\", \"authenticated\": true, \"name\": \"user\", \"keyHash\": "+key.hashCode()+","+ - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - AnonymousAuthenticationToken token = new AnonymousAuthenticationToken( - key, "user", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")) - ); - String actualJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, actualJson, true); - } + @Test + public void serializeAnonymousAuthenticationTokenTest() throws JsonProcessingException, JSONException { + String key = "key"; + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+ + "\"principal\": \"user\", \"credentials\": \"\", \"authenticated\": true, \"name\": \"user\", \"keyHash\": "+key.hashCode()+","+ + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + AnonymousAuthenticationToken token = new AnonymousAuthenticationToken( + key, "user", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")) + ); + String actualJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } - @Test - public void deserializeAnonymousAuthenticationTokenTest() throws IOException { - String key = "123456789"; - String jsonString = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+ - "\"principal\": \"user\", \"credentials\": \"\", \"authenticated\": true, \"name\": \"user\", \"keyHash\": "+key.hashCode()+","+ - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - AnonymousAuthenticationToken token = buildObjectMapper().readValue(jsonString, AnonymousAuthenticationToken.class); - assertThat(token).isNotNull(); - assertThat(token.getKeyHash()).isEqualTo(key.hashCode()); - assertThat(token.getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); - } + @Test + public void deserializeAnonymousAuthenticationTokenTest() throws IOException { + String key = "123456789"; + String jsonString = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+ + "\"principal\": \"user\", \"credentials\": \"\", \"authenticated\": true, \"name\": \"user\", \"keyHash\": "+key.hashCode()+","+ + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + AnonymousAuthenticationToken token = buildObjectMapper().readValue(jsonString, AnonymousAuthenticationToken.class); + assertThat(token).isNotNull(); + assertThat(token.getKeyHash()).isEqualTo(key.hashCode()); + assertThat(token.getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + } - @Test(expected = JsonMappingException.class) - public void deserializeAnonymousAuthenticationTokenWithoutAuthoritiesTest() throws IOException { - String key = "123456789"; - String jsonString = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+ - "\"principal\": \"user\", \"credentials\": \"\", \"authenticated\": true, \"name\": \"user\", \"keyHash\": "+key.hashCode()+","+ - "\"authorities\": [\"java.util.ArrayList\", []]}"; - buildObjectMapper().readValue(jsonString, AnonymousAuthenticationToken.class); - } + @Test(expected = JsonMappingException.class) + public void deserializeAnonymousAuthenticationTokenWithoutAuthoritiesTest() throws IOException { + String key = "123456789"; + String jsonString = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+ + "\"principal\": \"user\", \"credentials\": \"\", \"authenticated\": true, \"name\": \"user\", \"keyHash\": "+key.hashCode()+","+ + "\"authorities\": [\"java.util.ArrayList\", []]}"; + buildObjectMapper().readValue(jsonString, AnonymousAuthenticationToken.class); + } } diff --git a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java index 953635d48cd..64c46484d7f 100644 --- a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.core.JsonProcessingException; @@ -21,73 +37,73 @@ */ public class RememberMeAuthenticationTokenMixinTest extends AbstractMixinTests { - @Override - public ObjectMapper buildObjectMapper() { - return super.buildObjectMapper() - .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) - .addMixIn(User.class, UserMixin.class) - .addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class) - .addMixIn(RememberMeAuthenticationToken.class, RememberMeAuthenticationTokenMixin.class); - } + @Override + public ObjectMapper buildObjectMapper() { + return super.buildObjectMapper() + .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) + .addMixIn(User.class, UserMixin.class) + .addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class) + .addMixIn(RememberMeAuthenticationToken.class, RememberMeAuthenticationTokenMixin.class); + } - @Test(expected = IllegalArgumentException.class) - public void testWithNullPrincipal() throws JsonProcessingException, JSONException { - new RememberMeAuthenticationToken("key", null, Collections.emptyList()); - } + @Test(expected = IllegalArgumentException.class) + public void testWithNullPrincipal() throws JsonProcessingException, JSONException { + new RememberMeAuthenticationToken("key", null, Collections.emptyList()); + } - @Test(expected = IllegalArgumentException.class) - public void testWithNullKey() throws JsonProcessingException, JSONException { - new RememberMeAuthenticationToken(null, "principal", Collections.emptyList()); - } + @Test(expected = IllegalArgumentException.class) + public void testWithNullKey() throws JsonProcessingException, JSONException { + new RememberMeAuthenticationToken(null, "principal", Collections.emptyList()); + } - @Test - public void serializeRememberMeAuthenticationToken() throws JsonProcessingException, JSONException { - String key = "rememberMe"; - RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(key, "user", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + - "\"keyHash\": "+key.hashCode()+", \"principal\": \"user\", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - String actualJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, actualJson, true); - } + @Test + public void serializeRememberMeAuthenticationToken() throws JsonProcessingException, JSONException { + String key = "rememberMe"; + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(key, "user", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + + "\"keyHash\": "+key.hashCode()+", \"principal\": \"user\", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + String actualJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } - @Test - public void serializeRememberMeAuthenticationWithUserToken() throws JsonProcessingException, JSONException { - String key = "rememberMe"; - List authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); - RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(key, new User("user", "password", authorities), authorities); - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + - "\"keyHash\": "+key.hashCode()+", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," + - "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"password\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]},"+ - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - String actualJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, actualJson, true); - } + @Test + public void serializeRememberMeAuthenticationWithUserToken() throws JsonProcessingException, JSONException { + String key = "rememberMe"; + List authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(key, new User("user", "password", authorities), authorities); + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + + "\"keyHash\": "+key.hashCode()+", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"password\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]},"+ + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + String actualJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } - @Test - public void deserializeRememberMeAuthenticationToken() throws IOException { - String key = "rememberMe"; - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + - "\"keyHash\": "+key.hashCode()+", \"principal\": \"user\", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - RememberMeAuthenticationToken token = buildObjectMapper().readValue(expectedJson, RememberMeAuthenticationToken.class); - assertThat(token).isNotNull(); - assertThat(token.getPrincipal()).isNotNull().isEqualTo("user").isEqualTo(token.getName()); - assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); - } + @Test + public void deserializeRememberMeAuthenticationToken() throws IOException { + String key = "rememberMe"; + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + + "\"keyHash\": "+key.hashCode()+", \"principal\": \"user\", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + RememberMeAuthenticationToken token = buildObjectMapper().readValue(expectedJson, RememberMeAuthenticationToken.class); + assertThat(token).isNotNull(); + assertThat(token.getPrincipal()).isNotNull().isEqualTo("user").isEqualTo(token.getName()); + assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + } - @Test - public void deserializeRememberMeAuthenticationTokenWithUserTest() throws IOException { - String key = "rememberMe"; - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + - "\"keyHash\": "+key.hashCode()+", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," + - "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"password\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]},"+ - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - RememberMeAuthenticationToken token = buildObjectMapper().readValue(expectedJson, RememberMeAuthenticationToken.class); - assertThat(token).isNotNull(); - assertThat(token.getPrincipal()).isNotNull().isInstanceOf(User.class); - assertThat(((User)token.getPrincipal()).getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); - assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); - assertThat(((User)token.getPrincipal()).isEnabled()).isEqualTo(true); - } + @Test + public void deserializeRememberMeAuthenticationTokenWithUserTest() throws IOException { + String key = "rememberMe"; + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + + "\"keyHash\": "+key.hashCode()+", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"password\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]},"+ + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + RememberMeAuthenticationToken token = buildObjectMapper().readValue(expectedJson, RememberMeAuthenticationToken.class); + assertThat(token).isNotNull(); + assertThat(token.getPrincipal()).isNotNull().isInstanceOf(User.class); + assertThat(((User)token.getPrincipal()).getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + assertThat(((User)token.getPrincipal()).isEnabled()).isEqualTo(true); + } } diff --git a/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java index be7d341931f..8fd6bdee97b 100644 --- a/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.core.JsonProcessingException; @@ -20,41 +36,41 @@ */ public class SecurityContextMixinTest extends AbstractMixinTests { - @Override - protected ObjectMapper buildObjectMapper() { - return super.buildObjectMapper() - .addMixIn(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class) - .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class); - } - - @Test - public void securityContextSerializeTest() throws JsonProcessingException, JSONException { - String expectedJson = "{\"@class\": \"org.springframework.security.core.context.SecurityContextImpl\", \"authentication\": " + - "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - "\"principal\": \"user\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, \"name\": \"user\"," + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]" + - "}" + - "}"; - SecurityContext context = new SecurityContextImpl(); - context.setAuthentication(new UsernamePasswordAuthenticationToken("user", "password", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")))); - String actualJson = buildObjectMapper().writeValueAsString(context); - JSONAssert.assertEquals(expectedJson, actualJson, true); - } - - @Test - public void securityContextDeserializeTest() throws IOException { - String contextJson = "{\"@class\": \"org.springframework.security.core.context.SecurityContextImpl\", \"authentication\": " + - "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - "\"principal\": \"user\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, \"name\": \"user\"," + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]" + - "}" + - "}"; - SecurityContext context = buildObjectMapper().readValue(contextJson, SecurityContextImpl.class); - assertThat(context).isNotNull(); - assertThat(context.getAuthentication()).isNotNull().isInstanceOf(UsernamePasswordAuthenticationToken.class); - assertThat(context.getAuthentication().getPrincipal()).isEqualTo("user"); - assertThat(context.getAuthentication().getCredentials()).isEqualTo("password"); - assertThat(context.getAuthentication().isAuthenticated()).isEqualTo(true); - assertThat(context.getAuthentication().getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); - } + @Override + protected ObjectMapper buildObjectMapper() { + return super.buildObjectMapper() + .addMixIn(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class) + .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class); + } + + @Test + public void securityContextSerializeTest() throws JsonProcessingException, JSONException { + String expectedJson = "{\"@class\": \"org.springframework.security.core.context.SecurityContextImpl\", \"authentication\": " + + "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + "\"principal\": \"user\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, \"name\": \"user\"," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]" + + "}" + + "}"; + SecurityContext context = new SecurityContextImpl(); + context.setAuthentication(new UsernamePasswordAuthenticationToken("user", "password", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")))); + String actualJson = buildObjectMapper().writeValueAsString(context); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } + + @Test + public void securityContextDeserializeTest() throws IOException { + String contextJson = "{\"@class\": \"org.springframework.security.core.context.SecurityContextImpl\", \"authentication\": " + + "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + "\"principal\": \"user\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, \"name\": \"user\"," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]" + + "}" + + "}"; + SecurityContext context = buildObjectMapper().readValue(contextJson, SecurityContextImpl.class); + assertThat(context).isNotNull(); + assertThat(context.getAuthentication()).isNotNull().isInstanceOf(UsernamePasswordAuthenticationToken.class); + assertThat(context.getAuthentication().getPrincipal()).isEqualTo("user"); + assertThat(context.getAuthentication().getCredentials()).isEqualTo("password"); + assertThat(context.getAuthentication().isAuthenticated()).isEqualTo(true); + assertThat(context.getAuthentication().getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + } } diff --git a/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java index 539b1c1b223..1a748654c9e 100644 --- a/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.core.JsonProcessingException; @@ -20,33 +36,33 @@ */ public class SimpleGrantedAuthorityMixinTest { - ObjectMapper mapper; - - @Before - public void setup() { - mapper = new ObjectMapper(); - mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class); - } - - @Test - public void serializeSimpleGrantedAuthorityTest() throws JsonProcessingException, JSONException { - SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); - String serializeJson = mapper.writeValueAsString(authority); - String expectedJson = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}"; - JSONAssert.assertEquals(expectedJson, serializeJson, true); - } - - @Test - public void deserializeGrantedAuthorityTest() throws IOException { - String json = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}"; - SimpleGrantedAuthority authority = mapper.readValue(json, SimpleGrantedAuthority.class); - assertThat(authority).isNotNull(); - assertThat(authority.getAuthority()).isNotNull().isEqualTo("ROLE_USER"); - } - - @Test(expected = JsonMappingException.class) - public void deserializeGrantedAuthorityWithoutRoleTest() throws IOException { - String json = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\"}"; - mapper.readValue(json, SimpleGrantedAuthority.class); - } + ObjectMapper mapper; + + @Before + public void setup() { + mapper = new ObjectMapper(); + mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class); + } + + @Test + public void serializeSimpleGrantedAuthorityTest() throws JsonProcessingException, JSONException { + SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); + String serializeJson = mapper.writeValueAsString(authority); + String expectedJson = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}"; + JSONAssert.assertEquals(expectedJson, serializeJson, true); + } + + @Test + public void deserializeGrantedAuthorityTest() throws IOException { + String json = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}"; + SimpleGrantedAuthority authority = mapper.readValue(json, SimpleGrantedAuthority.class); + assertThat(authority).isNotNull(); + assertThat(authority.getAuthority()).isNotNull().isEqualTo("ROLE_USER"); + } + + @Test(expected = JsonMappingException.class) + public void deserializeGrantedAuthorityWithoutRoleTest() throws IOException { + String json = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\"}"; + mapper.readValue(json, SimpleGrantedAuthority.class); + } } diff --git a/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java b/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java index a7cc3a32883..0662b27546e 100644 --- a/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.core.JsonProcessingException; @@ -19,74 +35,74 @@ */ public class UserDeserializerTests extends AbstractMixinTests { - protected ObjectMapper buildObjectMapper() { - return super.buildObjectMapper() - .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) - .addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class) - .addMixIn(User.class, UserMixin.class); - } + protected ObjectMapper buildObjectMapper() { + return super.buildObjectMapper() + .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) + .addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class) + .addMixIn(User.class, UserMixin.class); + } - @Test - public void serializeUserTest() throws JsonProcessingException, JSONException { - ObjectMapper mapper = buildObjectMapper(); - User user = new User("admin", "1234", Collections.singletonList(new SimpleGrantedAuthority("USER_ROLE"))); - String userJson = mapper.writeValueAsString(user); - String expectedJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"admin\", \"password\": \"1234\", \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"USER_ROLE\"}]]}"; - JSONAssert.assertEquals(expectedJson, userJson, true); - } + @Test + public void serializeUserTest() throws JsonProcessingException, JSONException { + ObjectMapper mapper = buildObjectMapper(); + User user = new User("admin", "1234", Collections.singletonList(new SimpleGrantedAuthority("USER_ROLE"))); + String userJson = mapper.writeValueAsString(user); + String expectedJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"admin\", \"password\": \"1234\", \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"USER_ROLE\"}]]}"; + JSONAssert.assertEquals(expectedJson, userJson, true); + } - @Test - public void serializeUserWithoutAuthority() throws JsonProcessingException, JSONException { - ObjectMapper mapper = buildObjectMapper(); - User user = new User("admin", "1234", Collections.emptyList()); - String userJson = mapper.writeValueAsString(user); - String expectedJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"admin\", \"password\": \"1234\", \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", []]}"; - JSONAssert.assertEquals(expectedJson, userJson, true); - } + @Test + public void serializeUserWithoutAuthority() throws JsonProcessingException, JSONException { + ObjectMapper mapper = buildObjectMapper(); + User user = new User("admin", "1234", Collections.emptyList()); + String userJson = mapper.writeValueAsString(user); + String expectedJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"admin\", \"password\": \"1234\", \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", []]}"; + JSONAssert.assertEquals(expectedJson, userJson, true); + } - @Test(expected = IllegalArgumentException.class) - public void deserializeUserWithNullPasswordEmptyAuthorityTest() throws IOException { - String userJsonWithoutPasswordString = "{\"@class\": \"org.springframework.security.core.userdetails.User\", " + - "\"username\": \"user\", \"accountNonExpired\": true, " + - "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, " + - "\"authorities\": []}"; - ObjectMapper mapper = buildObjectMapper(); - mapper.readValue(userJsonWithoutPasswordString, User.class); - } + @Test(expected = IllegalArgumentException.class) + public void deserializeUserWithNullPasswordEmptyAuthorityTest() throws IOException { + String userJsonWithoutPasswordString = "{\"@class\": \"org.springframework.security.core.userdetails.User\", " + + "\"username\": \"user\", \"accountNonExpired\": true, " + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, " + + "\"authorities\": []}"; + ObjectMapper mapper = buildObjectMapper(); + mapper.readValue(userJsonWithoutPasswordString, User.class); + } - @Test - public void deserializeUserWithNullPasswordNoAuthorityTest() throws IOException { - String userJsonWithoutPasswordString = "{\"@class\": \"org.springframework.security.core.userdetails.User\", " + - "\"username\": \"user\", \"accountNonExpired\": true, " + - "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, " + - "\"authorities\": [\"java.util.HashSet\", []]}"; - ObjectMapper mapper = buildObjectMapper(); - User user = mapper.readValue(userJsonWithoutPasswordString, User.class); - assertThat(user).isNotNull(); - assertThat(user.getUsername()).isEqualTo("user"); - assertThat(user.getPassword()).isEqualTo(""); - assertThat(user.getAuthorities()).hasSize(0); - assertThat(user.isEnabled()).isEqualTo(true); - } + @Test + public void deserializeUserWithNullPasswordNoAuthorityTest() throws IOException { + String userJsonWithoutPasswordString = "{\"@class\": \"org.springframework.security.core.userdetails.User\", " + + "\"username\": \"user\", \"accountNonExpired\": true, " + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, " + + "\"authorities\": [\"java.util.HashSet\", []]}"; + ObjectMapper mapper = buildObjectMapper(); + User user = mapper.readValue(userJsonWithoutPasswordString, User.class); + assertThat(user).isNotNull(); + assertThat(user.getUsername()).isEqualTo("user"); + assertThat(user.getPassword()).isEqualTo(""); + assertThat(user.getAuthorities()).hasSize(0); + assertThat(user.isEnabled()).isEqualTo(true); + } - @Test(expected = IllegalArgumentException.class) - public void deserializeUserWithNoClassIdInAuthoritiesTest() throws IOException { - String userJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", " + - "\"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": false, " + - "\"accountNonLocked\": false, \"credentialsNonExpired\": false, \"enabled\": false, " + - "\"authorities\": [{\"role\": \"ROLE_USER\"}]}"; - buildObjectMapper().readValue(userJson, User.class); - } + @Test(expected = IllegalArgumentException.class) + public void deserializeUserWithNoClassIdInAuthoritiesTest() throws IOException { + String userJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", " + + "\"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": false, " + + "\"accountNonLocked\": false, \"credentialsNonExpired\": false, \"enabled\": false, " + + "\"authorities\": [{\"role\": \"ROLE_USER\"}]}"; + buildObjectMapper().readValue(userJson, User.class); + } - @Test - public void deserializeUserWithClassIdInAuthoritiesTest() throws IOException { - String userJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", " + - "\"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": true, " + - "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, " + - "\"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - User user = buildObjectMapper().readValue(userJson, User.class); - assertThat(user).isNotNull(); - assertThat(user.getUsername()).isEqualTo("user"); - assertThat(user.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); - } + @Test + public void deserializeUserWithClassIdInAuthoritiesTest() throws IOException { + String userJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", " + + "\"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": true, " + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, " + + "\"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + User user = buildObjectMapper().readValue(userJson, User.class); + assertThat(user).isNotNull(); + assertThat(user.getUsername()).isEqualTo("user"); + assertThat(user.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + } } diff --git a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java index 1dd49a05f77..32a6cc5b6ab 100644 --- a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.core.JsonProcessingException; @@ -20,86 +36,86 @@ */ public class UsernamePasswordAuthenticationTokenMixinTest extends AbstractMixinTests { - @Override - protected ObjectMapper buildObjectMapper() { - return super.buildObjectMapper() - .addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class) - .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) - .addMixIn(User.class, UserMixin.class) - .addMixIn(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class); - } + @Override + protected ObjectMapper buildObjectMapper() { + return super.buildObjectMapper() + .addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class) + .addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class) + .addMixIn(User.class, UserMixin.class) + .addMixIn(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class); + } - @Test - public void serializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws JsonProcessingException, JSONException { - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - " \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": false, \"details\": null, " + - "\"authorities\": [\"java.util.ArrayList\", []], \"name\": \"user1\"}"; - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user1", "password"); - String serializedJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, serializedJson, true); - } + @Test + public void serializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws JsonProcessingException, JSONException { + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + " \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": false, \"details\": null, " + + "\"authorities\": [\"java.util.ArrayList\", []], \"name\": \"user1\"}"; + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user1", "password"); + String serializedJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, serializedJson, true); + } - @Test - public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws JsonProcessingException, JSONException { - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - " \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, " + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]], \"name\": \"user1\"}"; - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user1", "password", Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"))); - String serializedJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, serializedJson, true); - } + @Test + public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws JsonProcessingException, JSONException { + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + " \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, " + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]], \"name\": \"user1\"}"; + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user1", "password", Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"))); + String serializedJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, serializedJson, true); + } - @Test - public void deserializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws IOException, JSONException { - String tokenJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - " \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": false, \"details\": null, " + - "\"authorities\": [\"java.util.ArrayList\", []], \"name\": \"user1\"}"; - UsernamePasswordAuthenticationToken token = buildObjectMapper().readValue(tokenJson, UsernamePasswordAuthenticationToken.class); - assertThat(token).isNotNull(); - assertThat(token.isAuthenticated()).isEqualTo(false); - assertThat(token.getAuthorities()).isNotNull().hasSize(0); - } + @Test + public void deserializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws IOException, JSONException { + String tokenJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + " \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": false, \"details\": null, " + + "\"authorities\": [\"java.util.ArrayList\", []], \"name\": \"user1\"}"; + UsernamePasswordAuthenticationToken token = buildObjectMapper().readValue(tokenJson, UsernamePasswordAuthenticationToken.class); + assertThat(token).isNotNull(); + assertThat(token.isAuthenticated()).isEqualTo(false); + assertThat(token.getAuthorities()).isNotNull().hasSize(0); + } - @Test - public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws IOException { - String tokenJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - "\"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, " + - "\"authorities\" : [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - UsernamePasswordAuthenticationToken token = buildObjectMapper().readValue(tokenJson, UsernamePasswordAuthenticationToken.class); - assertThat(token).isNotNull(); - assertThat(token.isAuthenticated()).isEqualTo(true); - assertThat(token.getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); - } + @Test + public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws IOException { + String tokenJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + "\"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, " + + "\"authorities\" : [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + UsernamePasswordAuthenticationToken token = buildObjectMapper().readValue(tokenJson, UsernamePasswordAuthenticationToken.class); + assertThat(token).isNotNull(); + assertThat(token.isAuthenticated()).isEqualTo(true); + assertThat(token.getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + } - @Test - public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinWithUserTest() throws JsonProcessingException, JSONException { - GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); - User user = new User("user", "pass", Collections.singleton(authority)); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, "pass", Collections.singleton(authority)); - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": true, \"enabled\": true, " + - "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + - "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"credentials\": \"pass\"," + - "\"details\": null, \"name\": \"user\", \"authenticated\": true," + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - String actualJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, actualJson, true); - } + @Test + public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinWithUserTest() throws JsonProcessingException, JSONException { + GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); + User user = new User("user", "pass", Collections.singleton(authority)); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, "pass", Collections.singleton(authority)); + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": true, \"enabled\": true, " + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + + "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"credentials\": \"pass\"," + + "\"details\": null, \"name\": \"user\", \"authenticated\": true," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + String actualJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } - @Test - public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenWithUserTest() throws IOException { - String tokenJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": true, \"enabled\": true, " + - "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + - "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"credentials\": \"pass\"," + - "\"details\": null, \"name\": \"user\", \"authenticated\": true," + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - ObjectMapper mapper = buildObjectMapper(); - UsernamePasswordAuthenticationToken token = mapper.readValue(tokenJson, UsernamePasswordAuthenticationToken.class); - assertThat(token).isNotNull(); - assertThat(token.getPrincipal()).isNotNull().isInstanceOf(User.class); - assertThat(((User)token.getPrincipal()).getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); - assertThat(token.isAuthenticated()).isEqualTo(true); - assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); - } + @Test + public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenWithUserTest() throws IOException { + String tokenJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": true, \"enabled\": true, " + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + + "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"credentials\": \"pass\"," + + "\"details\": null, \"name\": \"user\", \"authenticated\": true," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + ObjectMapper mapper = buildObjectMapper(); + UsernamePasswordAuthenticationToken token = mapper.readValue(tokenJson, UsernamePasswordAuthenticationToken.class); + assertThat(token).isNotNull(); + assertThat(token.getPrincipal()).isNotNull().isInstanceOf(User.class); + assertThat(((User)token.getPrincipal()).getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + assertThat(token.isAuthenticated()).isEqualTo(true); + assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + } } From d6d46588548912da0c6020bccc936b64bc364503 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 17:57:39 +0800 Subject: [PATCH 30/62] Space indentation removed to tab --- .../authentication/RememberMeAuthenticationToken.java | 3 +-- .../jackson2/AnonymousAuthenticationTokenMixin.java | 3 +-- .../jackson2/RememberMeAuthenticationTokenMixin.java | 4 +--- .../org/springframework/security/jackson2/UserMixin.java | 7 ++----- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java index 50d086963ed..90431ccf525 100644 --- a/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java @@ -74,8 +74,7 @@ public RememberMeAuthenticationToken(String key, Object principal, * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal */ - private RememberMeAuthenticationToken(Integer keyHash, Object principal, - Collection authorities) { + private RememberMeAuthenticationToken(Integer keyHash, Object principal, Collection authorities) { super(authorities); this.keyHash = keyHash; diff --git a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java index 1bb66328880..802eadc74bf 100644 --- a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java @@ -29,7 +29,6 @@ public class AnonymousAuthenticationTokenMixin { @JsonCreator - public AnonymousAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, - @JsonProperty("authorities") Collection authorities) { + public AnonymousAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, @JsonProperty("authorities") Collection authorities) { } } diff --git a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java index 2be534fbe59..a7727ef6620 100644 --- a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java @@ -32,8 +32,6 @@ public class RememberMeAuthenticationTokenMixin { @JsonCreator - public RememberMeAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, - @JsonProperty("principal") Object principal, - @JsonProperty("authorities") Collection authorities) { + public RememberMeAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, @JsonProperty("authorities") Collection authorities) { } } diff --git a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java index 17b15a7d840..4ab42af9bb1 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java @@ -30,9 +30,6 @@ @JsonDeserialize(using = UserDeserializer.class) public abstract class UserMixin { - public UserMixin(@JsonProperty("username") String username, @JsonProperty("password") String password, - @JsonProperty("enabled") boolean enabled, @JsonProperty("accountNonExpired") boolean accountNonExpired, - @JsonProperty("credentialsNonExpired") boolean credentialsNonExpired, - @JsonProperty("accountNonLocked") boolean accountNonLocked, @JsonProperty("authorities") Collection authorities) { - } + public UserMixin(@JsonProperty("username") String username, @JsonProperty("password") String password, @JsonProperty("enabled") boolean enabled, @JsonProperty("accountNonExpired") boolean accountNonExpired, @JsonProperty("credentialsNonExpired") boolean credentialsNonExpired, @JsonProperty("accountNonLocked") boolean accountNonLocked, @JsonProperty("authorities") Collection authorities) { + } } From 1cd5a700b48a34a63d4b96991a6d427d15bd9474 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Thu, 14 Apr 2016 18:15:53 +0800 Subject: [PATCH 31/62] Space indentation removed from UserMixin --- .../org/springframework/security/jackson2/UserMixin.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java index 4ab42af9bb1..d3328064f72 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java @@ -30,6 +30,10 @@ @JsonDeserialize(using = UserDeserializer.class) public abstract class UserMixin { - public UserMixin(@JsonProperty("username") String username, @JsonProperty("password") String password, @JsonProperty("enabled") boolean enabled, @JsonProperty("accountNonExpired") boolean accountNonExpired, @JsonProperty("credentialsNonExpired") boolean credentialsNonExpired, @JsonProperty("accountNonLocked") boolean accountNonLocked, @JsonProperty("authorities") Collection authorities) { - } + public UserMixin(@JsonProperty("username") String username, @JsonProperty("password") String password, + @JsonProperty("enabled") boolean enabled, @JsonProperty("accountNonExpired") boolean accountNonExpired, + @JsonProperty("credentialsNonExpired") boolean credentialsNonExpired, + @JsonProperty("accountNonLocked") boolean accountNonLocked, + @JsonProperty("authorities") Collection authorities) { + } } From 0039850a4bc378d3b1be47004499cd40e4709cff Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Fri, 15 Apr 2016 12:29:43 +0800 Subject: [PATCH 32/62] Code formatted single spaces removed added tab indentation --- .../cas/jackson2/AssertionImplMixin.java | 2 +- .../jackson2/AttributePrincipalImplMixin.java | 2 +- .../AnonymousAuthenticationTokenMixin.java | 3 +- .../RememberMeAuthenticationTokenMixin.java | 4 +- .../security/jackson2/UserMixin.java | 8 +- .../WebAuthenticationDetails.java | 20 +- .../web/jackson2/DefaultCsrfTokenMixin.java | 2 +- .../WebAuthenticationDetailsMixin.java | 2 +- .../web/savedrequest/DefaultSavedRequest.java | 296 +++++++++--------- 9 files changed, 171 insertions(+), 168 deletions(-) diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java index 661bcfbf4b3..80a63dcf245 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java @@ -37,4 +37,4 @@ public AssertionImplMixin(@JsonProperty("principal") AttributePrincipal principa @JsonProperty("validFromDate") Date validFromDate, @JsonProperty("validUntilDate") Date validUntilDate, @JsonProperty("authenticationDate") Date authenticationDate, @JsonProperty("attributes") Map attributes){ } -} +} \ No newline at end of file diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java index e78c97f0f37..44a63b07f45 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java @@ -34,4 +34,4 @@ public AttributePrincipalImplMixin(@JsonProperty("name") String name, @JsonPrope @JsonProperty("proxyGrantingTicket") String proxyGrantingTicket, @JsonProperty("proxyRetriever") ProxyRetriever proxyRetriever) { } -} +} \ No newline at end of file diff --git a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java index 802eadc74bf..ece38b1037b 100644 --- a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java @@ -29,6 +29,7 @@ public class AnonymousAuthenticationTokenMixin { @JsonCreator - public AnonymousAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, @JsonProperty("authorities") Collection authorities) { + public AnonymousAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, + @JsonProperty("authorities") Collection authorities) { } } diff --git a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java index a7727ef6620..b3386cef43f 100644 --- a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java @@ -32,6 +32,8 @@ public class RememberMeAuthenticationTokenMixin { @JsonCreator - public RememberMeAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, @JsonProperty("authorities") Collection authorities) { + public RememberMeAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, + @JsonProperty("principal") Object principal, + @JsonProperty("authorities") Collection authorities) { } } diff --git a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java index d3328064f72..9422773c27d 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java @@ -31,9 +31,9 @@ public abstract class UserMixin { public UserMixin(@JsonProperty("username") String username, @JsonProperty("password") String password, - @JsonProperty("enabled") boolean enabled, @JsonProperty("accountNonExpired") boolean accountNonExpired, - @JsonProperty("credentialsNonExpired") boolean credentialsNonExpired, - @JsonProperty("accountNonLocked") boolean accountNonLocked, - @JsonProperty("authorities") Collection authorities) { + @JsonProperty("enabled") boolean enabled, @JsonProperty("accountNonExpired") boolean accountNonExpired, + @JsonProperty("credentialsNonExpired") boolean credentialsNonExpired, + @JsonProperty("accountNonLocked") boolean accountNonLocked, + @JsonProperty("authorities") Collection authorities) { } } diff --git a/web/src/main/java/org/springframework/security/web/authentication/WebAuthenticationDetails.java b/web/src/main/java/org/springframework/security/web/authentication/WebAuthenticationDetails.java index a2675c60540..6957fa9753d 100644 --- a/web/src/main/java/org/springframework/security/web/authentication/WebAuthenticationDetails.java +++ b/web/src/main/java/org/springframework/security/web/authentication/WebAuthenticationDetails.java @@ -54,16 +54,16 @@ public WebAuthenticationDetails(HttpServletRequest request) { this.sessionId = (session != null) ? session.getId() : null; } - /** - * Constructor to add Jackson2 serialize/deserialize support - * - * @param remoteAddress remote address of current request - * @param sessionId session id - */ - private WebAuthenticationDetails(final String remoteAddress, final String sessionId) { - this.remoteAddress = remoteAddress; - this.sessionId = sessionId; - } + /** + * Constructor to add Jackson2 serialize/deserialize support + * + * @param remoteAddress remote address of current request + * @param sessionId session id + */ + private WebAuthenticationDetails(final String remoteAddress, final String sessionId) { + this.remoteAddress = remoteAddress; + this.sessionId = sessionId; + } // ~ Methods // ======================================================================================================== diff --git a/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java index 8e475326622..ea74c73fe9d 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java @@ -37,6 +37,6 @@ public class DefaultCsrfTokenMixin { */ @JsonCreator public DefaultCsrfTokenMixin(@JsonProperty("headerName") String headerName, - @JsonProperty("parameterName") String parameterName, @JsonProperty("token") String token) { + @JsonProperty("parameterName") String parameterName, @JsonProperty("token") String token) { } } diff --git a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java index 7e3cb824299..9e4c4763b77 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java @@ -28,6 +28,6 @@ public class WebAuthenticationDetailsMixin { @JsonCreator WebAuthenticationDetailsMixin(@JsonProperty("remoteAddress") String remoteAddress, - @JsonProperty("sessionId") String sessionId) { + @JsonProperty("sessionId") String sessionId) { } } diff --git a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java index f70294a61e1..5460458a18e 100644 --- a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java +++ b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java @@ -84,7 +84,7 @@ public DefaultSavedRequest(HttpServletRequest request, PortResolver portResolver Assert.notNull(portResolver, "PortResolver required"); // Cookies - addCookies(request.getCookies()); + addCookies(request.getCookies()); // Headers Enumeration names = request.getHeaderNames(); @@ -104,10 +104,10 @@ public DefaultSavedRequest(HttpServletRequest request, PortResolver portResolver } // Locales - addLocales(request.getLocales()); + addLocales(request.getLocales()); // Parameters - addParameters(request.getParameterMap()); + addParameters(request.getParameterMap()); // Primitives this.method = request.getMethod(); @@ -122,34 +122,34 @@ public DefaultSavedRequest(HttpServletRequest request, PortResolver portResolver this.servletPath = request.getServletPath(); } - /** - * Private constructor invoked through Builder - */ - private DefaultSavedRequest(String contextPath, String method, String pathInfo, String queryString, String requestURI, - String requestURL, String scheme, String serverName, String servletPath, int serverPort) { - - this.contextPath = contextPath; - this.method = method; - this.pathInfo = pathInfo; - this.queryString = queryString; - this.requestURI = requestURI; - this.requestURL = requestURL; - this.scheme = scheme; - this.serverName = serverName; - this.servletPath = servletPath; - this.serverPort = serverPort; - } + /** + * Private constructor invoked through Builder + */ + private DefaultSavedRequest(String contextPath, String method, String pathInfo, String queryString, String requestURI, + String requestURL, String scheme, String serverName, String servletPath, int serverPort) { + + this.contextPath = contextPath; + this.method = method; + this.pathInfo = pathInfo; + this.queryString = queryString; + this.requestURI = requestURI; + this.requestURL = requestURL; + this.scheme = scheme; + this.serverName = serverName; + this.servletPath = servletPath; + this.serverPort = serverPort; + } // ~ Methods // ======================================================================================================== - private void addCookies(Cookie[] cookies) { - if (cookies != null) { - for (Cookie cookie : cookies) { - this.addCookie(cookie); - } - } - } + private void addCookies(Cookie[] cookies) { + if (cookies != null) { + for (Cookie cookie : cookies) { + this.addCookie(cookie); + } + } + } private void addCookie(Cookie cookie) { cookies.add(new SavedCookie(cookie)); @@ -166,29 +166,29 @@ private void addHeader(String name, String value) { values.add(value); } - private void addLocales(Enumeration locales) { - while (locales.hasMoreElements()) { - Locale locale = locales.nextElement(); - this.addLocale(locale); - } - } + private void addLocales(Enumeration locales) { + while (locales.hasMoreElements()) { + Locale locale = locales.nextElement(); + this.addLocale(locale); + } + } private void addLocale(Locale locale) { locales.add(locale); } - private void addParameters(Map parameters) { - for (String paramName : parameters.keySet()) { - Object paramValues = parameters.get(paramName); - if (paramValues instanceof String[]) { - this.addParameter(paramName, (String[]) paramValues); - } else { - if (logger.isWarnEnabled()) { - logger.warn("ServletRequest.getParameterMap() returned non-String array"); - } - } - } - } + private void addParameters(Map parameters) { + for (String paramName : parameters.keySet()) { + Object paramValues = parameters.get(paramName); + if (paramValues instanceof String[]) { + this.addParameter(paramName, (String[]) paramValues); + } else { + if (logger.isWarnEnabled()) { + logger.warn("ServletRequest.getParameterMap() returned non-String array"); + } + } + } + } private void addParameter(String name, String[] values) { parameters.put(name, values); @@ -339,109 +339,6 @@ public String getServletPath() { return servletPath; } - public static class Builder { - - private List cookies = null; - private List locales = null; - private Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); - private Map parameters = new TreeMap(); - private String contextPath; - private String method; - private String pathInfo; - private String queryString; - private String requestURI; - private String requestURL; - private String scheme; - private String serverName; - private String servletPath; - private int serverPort = 80; - - public Builder setCookies(List cookies) { - this.cookies = cookies; - return this; - } - - public Builder setLocales(List locales) { - this.locales = locales; - return this; - } - - public Builder setHeaders(Map> header) { - this.headers.putAll(header); - return this; - } - - public Builder setParameters(Map parameters) { - this.parameters = parameters; - return this; - } - - public Builder setContextPath(String contextPath) { - this.contextPath = contextPath; - return this; - } - - public Builder setMethod(String method) { - this.method = method; - return this; - } - - public Builder setPathInfo(String pathInfo) { - this.pathInfo = pathInfo; - return this; - } - - public Builder setQueryString(String queryString) { - this.queryString = queryString; - return this; - } - - public Builder setRequestURI(String requestURI) { - this.requestURI = requestURI; - return this; - } - - public Builder setRequestURL(String requestURL) { - this.requestURL = requestURL; - return this; - } - - public Builder setScheme(String scheme) { - this.scheme = scheme; - return this; - } - - public Builder setServerName(String serverName) { - this.serverName = serverName; - return this; - } - - public Builder setServletPath(String servletPath) { - this.servletPath = servletPath; - return this; - } - - public Builder setServerPort(int serverPort) { - this.serverPort = serverPort; - return this; - } - - public DefaultSavedRequest build() { - DefaultSavedRequest savedRequest = new DefaultSavedRequest( - this.contextPath, this.method, this.pathInfo, this.queryString, this.requestURI, - this.requestURL, this.scheme, this.serverName, this.servletPath, this.serverPort - ); - savedRequest.addCookies(this.cookies.toArray(new Cookie[]{})); - savedRequest.locales.addAll(this.locales); - savedRequest.addParameters(this.parameters); - - this.headers.remove(HEADER_IF_MODIFIED_SINCE); - this.headers.remove(HEADER_IF_NONE_MATCH); - savedRequest.headers.putAll(this.headers); - return savedRequest; - } - } - private boolean propertyEquals(String log, Object arg1, Object arg2) { if ((arg1 == null) && (arg2 == null)) { if (logger.isDebugEnabled()) { @@ -481,4 +378,107 @@ private boolean propertyEquals(String log, Object arg1, Object arg2) { public String toString() { return "DefaultSavedRequest[" + getRedirectUrl() + "]"; } + + public static class Builder { + + private List cookies = null; + private List locales = null; + private Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + private Map parameters = new TreeMap(); + private String contextPath; + private String method; + private String pathInfo; + private String queryString; + private String requestURI; + private String requestURL; + private String scheme; + private String serverName; + private String servletPath; + private int serverPort = 80; + + public Builder setCookies(List cookies) { + this.cookies = cookies; + return this; + } + + public Builder setLocales(List locales) { + this.locales = locales; + return this; + } + + public Builder setHeaders(Map> header) { + this.headers.putAll(header); + return this; + } + + public Builder setParameters(Map parameters) { + this.parameters = parameters; + return this; + } + + public Builder setContextPath(String contextPath) { + this.contextPath = contextPath; + return this; + } + + public Builder setMethod(String method) { + this.method = method; + return this; + } + + public Builder setPathInfo(String pathInfo) { + this.pathInfo = pathInfo; + return this; + } + + public Builder setQueryString(String queryString) { + this.queryString = queryString; + return this; + } + + public Builder setRequestURI(String requestURI) { + this.requestURI = requestURI; + return this; + } + + public Builder setRequestURL(String requestURL) { + this.requestURL = requestURL; + return this; + } + + public Builder setScheme(String scheme) { + this.scheme = scheme; + return this; + } + + public Builder setServerName(String serverName) { + this.serverName = serverName; + return this; + } + + public Builder setServletPath(String servletPath) { + this.servletPath = servletPath; + return this; + } + + public Builder setServerPort(int serverPort) { + this.serverPort = serverPort; + return this; + } + + public DefaultSavedRequest build() { + DefaultSavedRequest savedRequest = new DefaultSavedRequest( + this.contextPath, this.method, this.pathInfo, this.queryString, this.requestURI, + this.requestURL, this.scheme, this.serverName, this.servletPath, this.serverPort + ); + savedRequest.addCookies(this.cookies.toArray(new Cookie[]{})); + savedRequest.locales.addAll(this.locales); + savedRequest.addParameters(this.parameters); + + this.headers.remove(HEADER_IF_MODIFIED_SINCE); + this.headers.remove(HEADER_IF_NONE_MATCH); + savedRequest.headers.putAll(this.headers); + return savedRequest; + } + } } From 7f576ca0e1862dfca18dc4e557426e315728dbb2 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Fri, 22 Apr 2016 10:41:48 +0530 Subject: [PATCH 33/62] Documentation added for mixin classes in cas module --- .../cas/jackson2/AssertionImplMixin.java | 20 +++++++++++ .../jackson2/AttributePrincipalImplMixin.java | 17 +++++++++ .../jackson2/CasAuthenticationTokenMixin.java | 35 +++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java index 80a63dcf245..87028e5c069 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java @@ -21,17 +21,37 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.jasig.cas.client.authentication.AttributePrincipal; +import org.springframework.security.cas.authentication.CasAuthenticationToken; import java.util.Date; import java.util.Map; /** + * Helps in jackson deserialization of class {@link org.jasig.cas.client.validation.AssertionImpl}, which is + * used with {@link org.springframework.security.cas.authentication.CasAuthenticationToken}. + * To use this class we need to register with {@link com.fasterxml.jackson.databind.ObjectMapper}. Type information + * will be stored in @class property. + *

+ *

+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.addMixIn(AssertionImpl.class, AssertionImplMixin.class);
+ * 
+ * * @author Jitendra Singh */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonIgnoreProperties(value = {"valid"}) public class AssertionImplMixin { + /** + * Mixin Constructor helps in deserialize {@link org.jasig.cas.client.validation.AssertionImpl} + * + * @param principal the Principal to associate with the Assertion. + * @param validFromDate when the assertion is valid from. + * @param validUntilDate when the assertion is valid to. + * @param authenticationDate when the assertion is authenticated. + * @param attributes the key/value pairs for this attribute. + */ @JsonCreator public AssertionImplMixin(@JsonProperty("principal") AttributePrincipal principal, @JsonProperty("validFromDate") Date validFromDate, @JsonProperty("validUntilDate") Date validUntilDate, diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java index 44a63b07f45..31483744a9d 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java @@ -24,11 +24,28 @@ import java.util.Map; /** + * Helps in deserialize {@link org.jasig.cas.client.authentication.AttributePrincipalImpl} which is used with + * {@link org.springframework.security.cas.authentication.CasAuthenticationToken}. Type information will be stored + * in property named @class. + *

+ *

+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.addMixIn(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class);
+ * 
+ * * @author Jitendra Singh */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) public class AttributePrincipalImplMixin { + /** + * Mixin Constructor helps in deserialize {@link org.jasig.cas.client.authentication.AttributePrincipalImpl} + * + * @param name the unique identifier for the principal. + * @param attributes the key/value pairs for this principal. + * @param proxyGrantingTicket the ticket associated with this principal. + * @param proxyRetriever the ProxyRetriever implementation to call back to the CAS server. + */ @JsonCreator public AttributePrincipalImplMixin(@JsonProperty("name") String name, @JsonProperty("attributes") Map attributes, @JsonProperty("proxyGrantingTicket") String proxyGrantingTicket, diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java index a91c686d712..2d5af2ce562 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java @@ -21,18 +21,53 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.jasig.cas.client.validation.Assertion; +import org.springframework.security.cas.authentication.CasAuthenticationProvider; +import org.springframework.security.cas.authentication.CasAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; /** + * Mixin class which helps in deserialize {@link org.springframework.security.cas.authentication.CasAuthenticationToken} + * using jackson. Two more dependent classes needs to register along with this mixin class. + *
    + *
  1. {@link org.springframework.security.cas.jackson2.AssertionImplMixin}
  2. + *
  3. {@link org.springframework.security.cas.jackson2.AttributePrincipalImplMixin}
  4. + *
+ * + *

+ * + *

+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.addMixIn(AssertionImpl.class, AssertionImplMixin.class);
+ *     mapper.addMixIn(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class);
+ *     mapper.addMixIn(CasAuthenticationToken.class, CasAuthenticationTokenMixin.class);
+ * 
+ * * @author Jitendra Singh */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonIgnoreProperties(ignoreUnknown = true) public class CasAuthenticationTokenMixin { + /** + * Mixin Constructor helps in deserialize {@link CasAuthenticationToken} + * + * @param keyHash hashCode of provided key to identify if this object made by a given + * {@link CasAuthenticationProvider} + * @param principal typically the UserDetails object (cannot be null) + * @param credentials the service/proxy ticket ID from CAS (cannot be + * null) + * @param authorities the authorities granted to the user (from the + * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot + * be null) + * @param userDetails the user details (from the + * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot + * be null) + * @param assertion the assertion returned from the CAS servers. It contains the + * principal and how to obtain a proxy ticket for the user. + */ @JsonCreator public CasAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, @JsonProperty("credentials") Object credentials, From 9afb364116b034468ad79b312bf082bcc40d513a Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Fri, 22 Apr 2016 13:00:57 +0530 Subject: [PATCH 34/62] No need of constructor because Deserializer is already registered --- .../springframework/security/jackson2/UserMixin.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java index 9422773c27d..bd81c2713e7 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java @@ -16,12 +16,8 @@ package org.springframework.security.jackson2; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import org.springframework.security.core.GrantedAuthority; - -import java.util.Collection; /** * @author Jitendra Singh @@ -29,11 +25,4 @@ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonDeserialize(using = UserDeserializer.class) public abstract class UserMixin { - - public UserMixin(@JsonProperty("username") String username, @JsonProperty("password") String password, - @JsonProperty("enabled") boolean enabled, @JsonProperty("accountNonExpired") boolean accountNonExpired, - @JsonProperty("credentialsNonExpired") boolean credentialsNonExpired, - @JsonProperty("accountNonLocked") boolean accountNonLocked, - @JsonProperty("authorities") Collection authorities) { - } } From 993188bb744ae6e716f1c51563d29a957bba1729 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Fri, 22 Apr 2016 13:18:14 +0530 Subject: [PATCH 35/62] Documentation added in core module mixin classes --- .../AnonymousAuthenticationTokenMixin.java | 20 +++++++++++++ .../RememberMeAuthenticationTokenMixin.java | 28 +++++++++++++++++++ .../jackson2/SimpleGrantedAuthorityMixin.java | 17 +++++++++++ .../jackson2/UnmodifiableSetMixin.java | 12 ++++++++ .../security/jackson2/UserDeserializer.java | 15 ++++++++++ .../security/jackson2/UserMixin.java | 14 ++++++++++ ...sswordAuthenticationTokenDeserializer.java | 17 +++++++++++ ...rnamePasswordAuthenticationTokenMixin.java | 18 ++++++++++++ .../security/jackson2/package-info.java | 6 +++- 9 files changed, 146 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java index ece38b1037b..a7e2136d76a 100644 --- a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java @@ -22,12 +22,32 @@ import java.util.Collection; /** + * This is a Jackson mixin class helps in serialize/deserialize + * {@link org.springframework.security.authentication.AnonymousAuthenticationToken} class. To use this class you need to register it + * with {@link com.fasterxml.jackson.databind.ObjectMapper} and {@link SimpleGrantedAuthorityMixin} because + * AnonymousAuthenticationToken contains SimpleGrantedAuthority. + *
+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
+ *     mapper.addMixIn(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class);
+ * 
+ * + * Note: This class will save full class name into a property called @class + * * @author Jitendra Singh */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonIgnoreProperties(ignoreUnknown = true) public class AnonymousAuthenticationTokenMixin { + /** + * Constructor used by Jackson to create object of {@link org.springframework.security.authentication.AnonymousAuthenticationToken}. + * + * @param keyHash hashCode of key provided at the time of token creation by using + * {@link org.springframework.security.authentication.AnonymousAuthenticationToken#AnonymousAuthenticationToken(String, Object, Collection)} + * @param principal the principal (typically a UserDetails) + * @param authorities the authorities granted to the principal + */ @JsonCreator public AnonymousAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, @JsonProperty("authorities") Collection authorities) { diff --git a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java index b3386cef43f..cebdef4a7fb 100644 --- a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java @@ -25,12 +25,40 @@ import java.util.Collection; /** + * This mixin class helps in serialize/deserialize + * {@link org.springframework.security.authentication.RememberMeAuthenticationToken} class. To use this class you need to register it + * with {@link com.fasterxml.jackson.databind.ObjectMapper} and 2 more mixin classes. + * + *
    + *
  1. {@link SimpleGrantedAuthorityMixin}
  2. + *
  3. {@link UserMixin}
  4. + *
  5. {@link UnmodifiableSetMixin}
  6. + *
+ * + *
+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
+ *     mapper.addMixIn({@link org.springframework.security.core.userdetails.User}.class, UserMixin.class);
+ *     mapper.addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class);
+ *     mapper.addMixIn(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class);
+ * 
+ * + * Note: This class will save TypeInfo (full class name) into a property called @class + * * @author Jitendra Singh */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonIgnoreProperties(ignoreUnknown = true) public class RememberMeAuthenticationTokenMixin { + /** + * Constructor used by Jackson to create + * {@link org.springframework.security.authentication.RememberMeAuthenticationToken} object. + * + * @param keyHash hashCode of above given key. + * @param principal the principal (typically a UserDetails) + * @param authorities the authorities granted to the principal + */ @JsonCreator public RememberMeAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, diff --git a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java index 2dd80db4291..554882cffed 100644 --- a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java @@ -23,16 +23,33 @@ import java.util.Collection; /** + * Jackson Mixin class helps in serialize/deserialize + * {@link org.springframework.security.core.authority.SimpleGrantedAuthority}. + * + *
+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
+ * 
* @author Jitendra Singh */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonIgnoreProperties(ignoreUnknown = true) public abstract class SimpleGrantedAuthorityMixin { + /** + * Mixin Constructor. + * @param role + */ @JsonCreator public SimpleGrantedAuthorityMixin(@JsonProperty("role") String role) { } + /** + * This method will ensure that getAuthority() doesn't serialized to authority key, it will be serialized + * as role key. Because above mixin constructor will look for role key to properly deserialize. + * + * @return + */ @JsonProperty("role") public abstract String getAuthority(); } diff --git a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java index 5b41708222a..029fe390f27 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java @@ -22,11 +22,23 @@ import java.util.Set; /** + * This mixin class used to deserialize java.util.Collections$UnmodifiableSet and used with various AuthenticationToken + * implementation's mixin classes. + * + *
+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class);
+ * 
+ * * @author Jitendra Singh */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) public class UnmodifiableSetMixin { + /** + * Mixin Constructor + * @param s + */ @JsonCreator UnmodifiableSetMixin(Set s) {} } diff --git a/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java b/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java index f8533ecb436..2f605d4ec09 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java +++ b/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java @@ -32,10 +32,25 @@ import java.util.Set; /** + * Custom Deserializer for {@link User} class. This is already registered with {@link UserMixin}. + * You can also use it directly with your mixin class. + * * @author Jitendra Singh + * @see UserMixin */ public class UserDeserializer extends JsonDeserializer { + /** + * This method will create {@link User} object. It will ensure successful object creation even if password key is null in + * serialized json, because credentials may be removed from the {@link User} by invoking {@link User#eraseCredentials()}. + * In that case there won't be any password key in serialized json. + * + * @param jp + * @param ctxt + * @return + * @throws IOException + * @throws JsonProcessingException + */ @Override public User deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { ObjectMapper mapper = (ObjectMapper) jp.getCodec(); diff --git a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java index bd81c2713e7..ecfd2076fba 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java @@ -20,7 +20,21 @@ 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. + *
    + *
  1. {@link SimpleGrantedAuthorityMixin}
  2. + *
  3. {@link UnmodifiableSetMixin}
  4. + *
+ *
+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
+ *     mapper.addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class);
+ * 
+ * * @author Jitendra Singh + * @see UserDeserializer */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonDeserialize(using = UserDeserializer.class) diff --git a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java index 8ef3e1aaf20..b7de26fbfce 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java +++ b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java @@ -32,10 +32,27 @@ import java.util.List; /** + * 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 */ public class UsernamePasswordAuthenticationTokenDeserializer extends JsonDeserializer { + /** + * This method construct {@link UsernamePasswordAuthenticationToken} object from serialized json. + * + * @param jp + * @param ctxt + * @return + * @throws IOException + * @throws JsonProcessingException + */ @Override public UsernamePasswordAuthenticationToken deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { UsernamePasswordAuthenticationToken token = null; diff --git a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java index a0b375a2022..35f16a9288b 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java @@ -20,6 +20,24 @@ 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. + *

    + *
  1. {@link UnmodifiableSetMixin}
  2. + *
  3. {@link SimpleGrantedAuthorityMixin}
  4. + *
  5. {@link UserMixin}
  6. + *
+ * + *
+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class);
+ *     mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
+ *     mapper.addMixIn(User.class, UserMixin.class);
+ *     mapper.addMixIn(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class);
+ * 
* @author Jitendra Singh */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") diff --git a/core/src/main/java/org/springframework/security/jackson2/package-info.java b/core/src/main/java/org/springframework/security/jackson2/package-info.java index a6b46f4706e..8c580bd59ee 100644 --- a/core/src/main/java/org/springframework/security/jackson2/package-info.java +++ b/core/src/main/java/org/springframework/security/jackson2/package-info.java @@ -16,4 +16,8 @@ /** * Mix-in classes to add Jackson serialization support. */ -package org.springframework.security.jackson2; \ No newline at end of file +package org.springframework.security.jackson2; + +/** + * Package contains Jackson mixin classes. + */ \ No newline at end of file From 04f9c55ebc3316ec7e375fa79ff4857be7c046bb Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Fri, 22 Apr 2016 14:26:21 +0530 Subject: [PATCH 36/62] Constructor removed because CookieDeserializer already registered --- .../springframework/security/web/jackson2/CookieMixin.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java index 8381eac8535..853a8925c9a 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java @@ -29,8 +29,4 @@ @JsonDeserialize(using = CookieDeserializer.class) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE) public abstract class CookieMixin { - - @JsonCreator - public CookieMixin(@JsonProperty("name") String name, @JsonProperty("value") String value) { - } } From 005e2635dfb6bb4eb419b3616915a714dd711810 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Tue, 26 Apr 2016 21:59:52 +0530 Subject: [PATCH 37/62] Documentation added for web module jackson mixin classes --- .../web/jackson2/CookieDeserializer.java | 6 +++ .../security/web/jackson2/CookieMixin.java | 9 ++++- .../web/jackson2/DefaultCsrfTokenMixin.java | 7 +++- .../jackson2/DefaultSavedRequestMixin.java | 15 +++++++ .../WebAuthenticationDetailsMixin.java | 7 ++++ .../WebAuthenticationDetailsMixinTest.java | 40 +++++++++++-------- 6 files changed, 64 insertions(+), 20 deletions(-) diff --git a/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java b/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java index 86d7712ae8c..38852edbf9e 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java @@ -29,7 +29,13 @@ import java.io.IOException; /** + * Jackson deserializer for {@link Cookie}. This is needed because in most cases we don't + * set {@link Cookie#domain} 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 */ public class CookieDeserializer extends JsonDeserializer { diff --git a/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java index 853a8925c9a..ae03001e23a 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java @@ -17,12 +17,17 @@ package org.springframework.security.web.jackson2; import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; 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.addMixIn(Cookie.class, CookieMixin.class);
+ * 
+ * * @author Jitendra Singh */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) diff --git a/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java index ea74c73fe9d..52ddf8de976 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java @@ -19,9 +19,14 @@ import com.fasterxml.jackson.annotation.*; /** - * Mix-in class for {@link org.springframework.security.web.csrf.DefaultCsrfToken} to enable Jackson + * Jackson mixin class to serialize/deserialize {@link org.springframework.security.web.csrf.DefaultCsrfToken} * serialization support. * + *
+ * 	ObjectMapper mapper = new ObjectMapper();
+ *	mapper.addMixIn(DefaultCsrfToken.class, DefaultCsrfTokenMixin.class);
+ * 
+ * * @author Jitendra Singh */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") diff --git a/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java index 08f7902221e..6e683488b6c 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java @@ -26,6 +26,17 @@ import java.util.Map; /** +` * Jackson mixin class to serialize/deserialize {@link DefaultSavedRequest}. This mixin use + * {@link org.springframework.security.web.savedrequest.DefaultSavedRequest.Builder} to + * deserialized josn.In order to use this mixin class you also need to register + * {@link CookieMixin}. + * + *
+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.addMixIn(Cookie.class, CookieMixin.class);
+ *     mapper.addMixIn(DefaultSavedRequest.class, DefaultSavedRequestMixin.class);
+ * 
+ * * @author Jitendra Singh */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @@ -36,6 +47,10 @@ ) public abstract class DefaultSavedRequestMixin { + /** + * This method will ensure that all the request parameters will must in 'parameters' key. + * @return + */ @JsonProperty("parameters") public abstract Map getParameterMap(); } diff --git a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java index 9e4c4763b77..d7272d74fdc 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java @@ -21,6 +21,13 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; /** + * Jackson mixin class to serialize/deserialize {@link org.springframework.security.web.WebAuthenticationDetails}. + * + *
+ * 	ObjectMapper mapper = new ObjectMapper();
+ *	mapper.addMixIn(WebAuthenticationDetails.class, WebAuthenticationDetailsMixin.class);
+ * 
+ * * @author Jitendra Singh */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) diff --git a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java index b54878828e2..87ae983d026 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java @@ -16,6 +16,8 @@ package org.springframework.security.web.jackson2; +import java.io.IOException; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.json.JSONException; @@ -24,13 +26,12 @@ import org.junit.runner.RunWith; import org.mockito.runners.MockitoJUnitRunner; import org.skyscreamer.jsonassert.JSONAssert; + import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpSession; import org.springframework.security.web.authentication.WebAuthenticationDetails; -import java.io.IOException; - -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Jitendra Singh @@ -42,40 +43,45 @@ public class WebAuthenticationDetailsMixinTest { @Before public void setup() { - mapper = new ObjectMapper() - .addMixIn(WebAuthenticationDetails.class, WebAuthenticationDetailsMixin.class); + this.mapper = new ObjectMapper().addMixIn(WebAuthenticationDetails.class, + WebAuthenticationDetailsMixin.class); } @Test - public void buildWebAuthenticationDetailsUsingDifferentConstructors() throws IOException { + public void buildWebAuthenticationDetailsUsingDifferentConstructors() + throws IOException { MockHttpServletRequest request = new MockHttpServletRequest(); request.setRemoteAddr("localhost"); request.setSession(new MockHttpSession(null, "1")); WebAuthenticationDetails details = new WebAuthenticationDetails(request); - String jsonString = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + - "\"sessionId\": \"1\", \"remoteAddress\": \"/localhost\"}"; - WebAuthenticationDetails authenticationDetails = mapper.readValue(jsonString, WebAuthenticationDetails.class); + String jsonString = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + + "\"sessionId\": \"1\", \"remoteAddress\": \"/localhost\"}"; + WebAuthenticationDetails authenticationDetails = this.mapper.readValue(jsonString, + WebAuthenticationDetails.class); assertThat(details.equals(authenticationDetails)); } @Test - public void webAuthenticationDetailsSerializeTest() throws JsonProcessingException, JSONException { + public void webAuthenticationDetailsSerializeTest() + throws JsonProcessingException, JSONException { MockHttpServletRequest request = new MockHttpServletRequest(); request.setRemoteAddr("/home"); request.setSession(new MockHttpSession(null, "1")); WebAuthenticationDetails details = new WebAuthenticationDetails(request); - String expectedJson = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + - "\"sessionId\": \"1\", \"remoteAddress\": \"/home\"}"; - String actualJson = mapper.writeValueAsString(details); + String expectedJson = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + + "\"sessionId\": \"1\", \"remoteAddress\": \"/home\"}"; + String actualJson = this.mapper.writeValueAsString(details); JSONAssert.assertEquals(expectedJson, actualJson, true); } @Test - public void webAuthenticationDetailsDeserializeTest() throws IOException, JSONException { - String actualJson = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + - "\"sessionId\": \"1\", \"remoteAddress\": \"/home\"}"; - WebAuthenticationDetails details = mapper.readValue(actualJson, WebAuthenticationDetails.class); + public void webAuthenticationDetailsDeserializeTest() + throws IOException, JSONException { + String actualJson = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + + "\"sessionId\": \"1\", \"remoteAddress\": \"/home\"}"; + WebAuthenticationDetails details = this.mapper.readValue(actualJson, + WebAuthenticationDetails.class); assertThat(details).isNotNull(); assertThat(details.getRemoteAddress()).isEqualTo("/home"); assertThat(details.getSessionId()).isEqualTo("1"); From 86ac453c4846f3cac7cd1258b4b5e7478a7409aa Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Wed, 27 Apr 2016 09:52:11 +0530 Subject: [PATCH 38/62] Package name corrected --- .../security/web/jackson2/WebAuthenticationDetailsMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java index d7272d74fdc..2bc16e737e3 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java @@ -21,7 +21,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; /** - * Jackson mixin class to serialize/deserialize {@link org.springframework.security.web.WebAuthenticationDetails}. + * Jackson mixin class to serialize/deserialize {@link org.springframework.security.web.authentication.WebAuthenticationDetails}. * *
  * 	ObjectMapper mapper = new ObjectMapper();

From f625580bdb14a877129f24c1200ed75d9ffb5c49 Mon Sep 17 00:00:00 2001
From: Jitendra Singh Bisht 
Date: Wed, 27 Apr 2016 09:52:28 +0530
Subject: [PATCH 39/62] extra space removed from docs

---
 .../UsernamePasswordAuthenticationTokenDeserializer.java         | 1 -
 1 file changed, 1 deletion(-)

diff --git a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java
index b7de26fbfce..e39bb3d0aeb 100644
--- a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java
+++ b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java
@@ -46,7 +46,6 @@ public class UsernamePasswordAuthenticationTokenDeserializer extends JsonDeseria
 
 	/**
 	 * This method construct {@link UsernamePasswordAuthenticationToken} object from serialized json.
-	 * 
 	 * @param jp
 	 * @param ctxt
 	 * @return

From 3d4b84f176c93502477855c8bcca1ffcf6506b47 Mon Sep 17 00:00:00 2001
From: Jitendra Singh Bisht 
Date: Sat, 9 Jul 2016 18:15:14 +0530
Subject: [PATCH 40/62] Ignore unknown properties configuration added in
 DefaultSavedRequests Builder

---
 .../security/web/savedrequest/DefaultSavedRequest.java          | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java
index 5460458a18e..8a2567e08e7 100644
--- a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java
+++ b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java
@@ -16,6 +16,7 @@
 
 package org.springframework.security.web.savedrequest;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.springframework.security.web.PortResolver;
@@ -379,6 +380,7 @@ public String toString() {
 		return "DefaultSavedRequest[" + getRedirectUrl() + "]";
 	}
 
+	@JsonIgnoreProperties(ignoreUnknown = true)
 	public static class Builder {
 
 		private List cookies = null;

From da104e818b58f7e62c46e0bcf828d6243f725f84 Mon Sep 17 00:00:00 2001
From: Jitendra Singh Bisht 
Date: Sat, 9 Jul 2016 18:15:22 +0530
Subject: [PATCH 41/62] Removed unused import

---
 .../security/cas/jackson2/AssertionImplMixin.java                | 1 -
 1 file changed, 1 deletion(-)

diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java
index 87028e5c069..cf7e78423bb 100644
--- a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java
+++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java
@@ -21,7 +21,6 @@
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import org.jasig.cas.client.authentication.AttributePrincipal;
-import org.springframework.security.cas.authentication.CasAuthenticationToken;
 
 import java.util.Date;
 import java.util.Map;

From 9fe6ba76b13c4e2a228518de6bd24d3a666751fc Mon Sep 17 00:00:00 2001
From: Jitendra Singh Bisht 
Date: Sat, 9 Jul 2016 18:16:01 +0530
Subject: [PATCH 42/62] Jackson SimpleModules added in core, web and cas module

---
 .../cas/jackson2/CasJackson2SimpleModule.java | 49 +++++++++++++++++++
 .../jackson2/CoreJackson2SimpleModule.java    | 41 ++++++++++++++++
 .../web/jackson2/WebJackson2SimpleModule.java | 36 ++++++++++++++
 3 files changed, 126 insertions(+)
 create mode 100644 cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2SimpleModule.java
 create mode 100644 core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java
 create mode 100644 web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java

diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2SimpleModule.java b/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2SimpleModule.java
new file mode 100644
index 00000000000..240f83df4d8
--- /dev/null
+++ b/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2SimpleModule.java
@@ -0,0 +1,49 @@
+/*
+ * 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.cas.jackson2;
+
+import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import org.jasig.cas.client.authentication.AttributePrincipalImpl;
+import org.jasig.cas.client.validation.AssertionImpl;
+import org.springframework.security.cas.authentication.CasAuthenticationToken;
+
+/**
+ * Jackson module for spring-security-cas. This module register {@link AssertionImplMixin},
+ * {@link AttributePrincipalImplMixin} and {@link CasAuthenticationTokenMixin}. In order to use this module just
+ * add this module into your ObjectMapper configuration.
+ *
+ * 
+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.registerModule(new CasJackson2SimpleModule());
+ * 
+ * + * @author Jitendra Singh. + */ +public class CasJackson2SimpleModule extends SimpleModule { + + public CasJackson2SimpleModule() { + super(CasJackson2SimpleModule.class.getName(), new Version(1, 0, 0, null, null, null)); + } + + @Override + public void setupModule(SetupContext context) { + context.setMixInAnnotations(AssertionImpl.class, AssertionImplMixin.class); + context.setMixInAnnotations(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class); + context.setMixInAnnotations(CasAuthenticationToken.class, CasAuthenticationTokenMixin.class); + } +} diff --git a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java new file mode 100644 index 00000000000..ea717142e4d --- /dev/null +++ b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java @@ -0,0 +1,41 @@ +package org.springframework.security.jackson2; + +import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.authentication.RememberMeAuthenticationToken; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; + +import java.util.Collections; + +/** + * Jackson module for spring-security-core. This module register {@link AnonymousAuthenticationTokenMixin}, + * {@link RememberMeAuthenticationTokenMixin}, {@link SimpleGrantedAuthorityMixin}, {@link UnmodifiableSetMixin}, + * {@link UserMixin} and {@link UsernamePasswordAuthenticationTokenMixin}. In order to use this module just + * add this module into your ObjectMapper configuration. + * + *
+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.registerModule(new CoreJackson2SimpleModule());
+ * 
+ * + * @author Jitendra Singh. + */ +public class CoreJackson2SimpleModule extends SimpleModule { + + public CoreJackson2SimpleModule() { + super(CoreJackson2SimpleModule.class.getName(), new Version(1, 0, 0, null, null, null)); + } + + @Override + public void setupModule(SetupContext context) { + context.setMixInAnnotations(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class); + context.setMixInAnnotations(RememberMeAuthenticationToken.class, RememberMeAuthenticationTokenMixin.class); + context.setMixInAnnotations(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class); + context.setMixInAnnotations(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class); + context.setMixInAnnotations(User.class, UserMixin.class); + context.setMixInAnnotations(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class); + } +} diff --git a/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java b/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java new file mode 100644 index 00000000000..963f3ebcdcd --- /dev/null +++ b/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java @@ -0,0 +1,36 @@ +package org.springframework.security.web.jackson2; + +import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.springframework.security.web.authentication.WebAuthenticationDetails; +import org.springframework.security.web.csrf.DefaultCsrfToken; +import org.springframework.security.web.savedrequest.DefaultSavedRequest; + +import javax.servlet.http.Cookie; + +/** + * Jackson module for spring-security-web. This module register {@link CookieMixin}, + * {@link DefaultCsrfTokenMixin}, {@link DefaultSavedRequestMixin} and {@link WebAuthenticationDetailsMixin}. + * In order to use this module just add this module into your ObjectMapper configuration. + * + *
+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.registerModule(new WebJackson2SimpleModule());
+ * 
+ * + * @author Jitendra Singh. + */ +public class WebJackson2SimpleModule extends SimpleModule { + + public WebJackson2SimpleModule() { + super(WebJackson2SimpleModule.class.getName(), new Version(1, 0, 0, null, null, null)); + } + + @Override + public void setupModule(SetupContext context) { + context.setMixInAnnotations(Cookie.class, CookieMixin.class); + context.setMixInAnnotations(DefaultCsrfToken.class, DefaultCsrfTokenMixin.class); + context.setMixInAnnotations(DefaultSavedRequest.class, DefaultSavedRequestMixin.class); + context.setMixInAnnotations(WebAuthenticationDetails.class, WebAuthenticationDetailsMixin.class); + } +} From effd806d52e90d2bd48a03f9af279bc6e6cc6123 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Mon, 11 Jul 2016 12:04:21 +0530 Subject: [PATCH 43/62] Licence header added in Core and Web Jackson module --- .../jackson2/CoreJackson2SimpleModule.java | 16 ++++++++++++++++ .../web/jackson2/WebJackson2SimpleModule.java | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java index ea717142e4d..74299340cb3 100644 --- a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java +++ b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.core.Version; diff --git a/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java b/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java index 963f3ebcdcd..a2706925384 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.core.Version; From 3a9635893ee53688194dc903142d214144e805a4 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Tue, 19 Jul 2016 17:26:36 +0530 Subject: [PATCH 44/62] javadoc @since 4.2 added in new class / methods / constructors --- .../authentication/CasAuthenticationToken.java | 2 ++ .../cas/jackson2/AssertionImplMixin.java | 1 + .../jackson2/AttributePrincipalImplMixin.java | 1 + .../jackson2/CasAuthenticationTokenMixin.java | 1 + .../cas/jackson2/CasJackson2SimpleModule.java | 1 + .../CasAuthenticationTokenMixinTest.java | 1 + .../AnonymousAuthenticationToken.java | 18 +++++++++--------- .../RememberMeAuthenticationToken.java | 14 +++++++------- .../AnonymousAuthenticationTokenMixin.java | 1 + .../jackson2/CoreJackson2SimpleModule.java | 1 + .../RememberMeAuthenticationTokenMixin.java | 1 + .../jackson2/SimpleGrantedAuthorityMixin.java | 1 + .../jackson2/UnmodifiableSetMixin.java | 1 + .../security/jackson2/UserDeserializer.java | 1 + .../security/jackson2/UserMixin.java | 1 + ...asswordAuthenticationTokenDeserializer.java | 1 + ...ernamePasswordAuthenticationTokenMixin.java | 1 + .../security/jackson2/package-info.java | 3 +++ .../security/jackson2/AbstractMixinTests.java | 1 + .../AnonymousAuthenticationTokenMixinTest.java | 1 + ...RememberMeAuthenticationTokenMixinTest.java | 1 + .../jackson2/SecurityContextMixinTest.java | 1 + .../SimpleGrantedAuthorityMixinTest.java | 3 ++- .../jackson2/UserDeserializerTests.java | 1 + ...mePasswordAuthenticationTokenMixinTest.java | 1 + .../web/jackson2/CookieDeserializer.java | 1 + .../security/web/jackson2/CookieMixin.java | 1 + .../web/jackson2/DefaultCsrfTokenMixin.java | 1 + .../web/jackson2/DefaultSavedRequestMixin.java | 1 + .../WebAuthenticationDetailsMixin.java | 1 + .../web/jackson2/WebJackson2SimpleModule.java | 3 ++- .../security/web/jackson2/package-info.java | 3 +++ .../web/savedrequest/DefaultSavedRequest.java | 12 ++++++++++++ .../security/web/jackson2/CookieMixinTest.java | 1 + .../jackson2/DefaultCsrfTokenMixinTests.java | 1 + .../jackson2/DefaultSavedRequestMixinTest.java | 1 + .../WebAuthenticationDetailsMixinTest.java | 1 + 37 files changed, 69 insertions(+), 18 deletions(-) diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java index 9ac0bf1e2db..c7081de6ea9 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java @@ -91,6 +91,8 @@ public CasAuthenticationToken(final String key, final Object principal, * principal and how to obtain a proxy ticket for the user. * * @throws IllegalArgumentException if a null was passed + * + * @since 4.2 */ private CasAuthenticationToken(final Integer keyHash, final Object principal, final Object credentials, diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java index cf7e78423bb..468574d1dc4 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java @@ -37,6 +37,7 @@ *
* * @author Jitendra Singh + * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonIgnoreProperties(value = {"valid"}) diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java index 31483744a9d..e83d59e8172 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java @@ -34,6 +34,7 @@ * * * @author Jitendra Singh + * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) public class AttributePrincipalImplMixin { diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java index 2d5af2ce562..7a607031225 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java @@ -46,6 +46,7 @@ * * * @author Jitendra Singh + * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2SimpleModule.java b/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2SimpleModule.java index 240f83df4d8..3c38564148f 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2SimpleModule.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2SimpleModule.java @@ -33,6 +33,7 @@ * * * @author Jitendra Singh. + * @since 4.2 */ public class CasJackson2SimpleModule extends SimpleModule { diff --git a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java index 02a81cb2048..1b223413f68 100644 --- a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java +++ b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java @@ -46,6 +46,7 @@ /** * @author Jitendra Singh + * @since 4.2 */ @RunWith(MockitoJUnitRunner.class) public class CasAuthenticationTokenMixinTest { diff --git a/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java index acdbf03c0d2..8e83f857fe8 100644 --- a/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java @@ -41,29 +41,29 @@ public class AnonymousAuthenticationToken extends AbstractAuthenticationToken im /** * Constructor. * - * @param key to identify if this object made by an authorised client - * @param principal the principal (typically a UserDetails) + * @param key to identify if this object made by an authorised client + * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal - * * @throws IllegalArgumentException if a null was passed */ public AnonymousAuthenticationToken(String key, Object principal, - Collection authorities) { + Collection authorities) { this(extractKeyHash(key), nullSafeValue(principal), authorities); } /** * Constructor helps in Jackson Deserialization * - * @param keyHash hashCode of provided Key, constructed by above constructor - * @param principal the principal (typically a UserDetails) + * @param keyHash hashCode of provided Key, constructed by above constructor + * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal - */ + * @since 4.2 + */ private AnonymousAuthenticationToken(Integer keyHash, Object principal, - Collection authorities) { + Collection authorities) { super(authorities); - if(authorities == null || authorities.isEmpty()) { + if (authorities == null || authorities.isEmpty()) { throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); } diff --git a/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java index 90431ccf525..4d663f70404 100644 --- a/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java @@ -23,7 +23,7 @@ /** * Represents a remembered Authentication. - *

+ *

* A remembered Authentication must provide a fully valid * Authentication, including the GrantedAuthoritys that apply. * @@ -46,14 +46,13 @@ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken { /** * Constructor. * - * @param key to identify if this object made by an authorised client - * @param principal the principal (typically a UserDetails) + * @param key to identify if this object made by an authorised client + * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal - * * @throws IllegalArgumentException if a null was passed */ public RememberMeAuthenticationToken(String key, Object principal, - Collection authorities) { + Collection authorities) { super(authorities); if ((key == null) || ("".equals(key)) || (principal == null) @@ -70,9 +69,10 @@ public RememberMeAuthenticationToken(String key, Object principal, /** * Private Constructor to help in Jackson deserialization. * - * @param keyHash hashCode of above given key. - * @param principal the principal (typically a UserDetails) + * @param keyHash hashCode of above given key. + * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal + * @since 4.2 */ private RememberMeAuthenticationToken(Integer keyHash, Object principal, Collection authorities) { super(authorities); diff --git a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java index a7e2136d76a..c323235dc23 100644 --- a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java @@ -35,6 +35,7 @@ * Note: This class will save full class name into a property called @class * * @author Jitendra Singh + * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java index 74299340cb3..bddee1839ed 100644 --- a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java +++ b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java @@ -38,6 +38,7 @@ * * * @author Jitendra Singh. + * @since 4.2 */ public class CoreJackson2SimpleModule extends SimpleModule { diff --git a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java index cebdef4a7fb..463322c2302 100644 --- a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java @@ -46,6 +46,7 @@ * Note: This class will save TypeInfo (full class name) into a property called @class * * @author Jitendra Singh + * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java index 554882cffed..d9fd5551b8c 100644 --- a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java @@ -31,6 +31,7 @@ * mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class); * * @author Jitendra Singh + * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java index 029fe390f27..d932af1bb09 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java @@ -31,6 +31,7 @@ * * * @author Jitendra Singh + * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) public class UnmodifiableSetMixin { diff --git a/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java b/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java index 2f605d4ec09..5367fd481e8 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java +++ b/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java @@ -37,6 +37,7 @@ * * @author Jitendra Singh * @see UserMixin + * @since 4.2 */ public class UserDeserializer extends JsonDeserializer { diff --git a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java index ecfd2076fba..04703c5378b 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java @@ -35,6 +35,7 @@ * * @author Jitendra Singh * @see UserDeserializer + * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonDeserialize(using = UserDeserializer.class) diff --git a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java index e39bb3d0aeb..985f605e4f3 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java +++ b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java @@ -41,6 +41,7 @@ * * @author Jitendra Singh * @see UsernamePasswordAuthenticationTokenMixin + * @since 4.2 */ public class UsernamePasswordAuthenticationTokenDeserializer extends JsonDeserializer { diff --git a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java index 35f16a9288b..4b985d383a4 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java @@ -39,6 +39,7 @@ * mapper.addMixIn(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class); * * @author Jitendra Singh + * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") @JsonDeserialize(using = UsernamePasswordAuthenticationTokenDeserializer.class) diff --git a/core/src/main/java/org/springframework/security/jackson2/package-info.java b/core/src/main/java/org/springframework/security/jackson2/package-info.java index 8c580bd59ee..fadd25a8cf5 100644 --- a/core/src/main/java/org/springframework/security/jackson2/package-info.java +++ b/core/src/main/java/org/springframework/security/jackson2/package-info.java @@ -15,6 +15,9 @@ */ /** * Mix-in classes to add Jackson serialization support. + * + * @author Jitendra Singh + * @since 4.2 */ package org.springframework.security.jackson2; diff --git a/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java index c1023061329..c9c4cba36e9 100644 --- a/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java @@ -25,6 +25,7 @@ /** * @author Jitenra Singh + * @since 4.2 */ @RunWith(MockitoJUnitRunner.class) public abstract class AbstractMixinTests { diff --git a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java index 434c30bb1d3..66c7d301058 100644 --- a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java @@ -34,6 +34,7 @@ /** * @author Jitendra Singh + * @since 4.2 */ public class AnonymousAuthenticationTokenMixinTest extends AbstractMixinTests { diff --git a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java index 64c46484d7f..f8ced739b55 100644 --- a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java @@ -34,6 +34,7 @@ /** * @author Jitendra Singh + * @since 4.2 */ public class RememberMeAuthenticationTokenMixinTest extends AbstractMixinTests { diff --git a/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java index 8fd6bdee97b..0761c9a64dd 100644 --- a/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java @@ -33,6 +33,7 @@ /** * @author Jitendra Singh + * @since 4.2 */ public class SecurityContextMixinTest extends AbstractMixinTests { diff --git a/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java index 1a748654c9e..8a136d18fde 100644 --- a/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java @@ -32,7 +32,8 @@ import static org.assertj.core.api.Assertions.*; /** - * @author Jitendra Singh. + * @author Jitendra Singh + * @since 4.2 */ public class SimpleGrantedAuthorityMixinTest { diff --git a/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java b/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java index 0662b27546e..81db18401fa 100644 --- a/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java @@ -32,6 +32,7 @@ /** * @author Jitendra Singh + * @since 4.2 */ public class UserDeserializerTests extends AbstractMixinTests { diff --git a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java index 32a6cc5b6ab..ef79f6139bc 100644 --- a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java @@ -33,6 +33,7 @@ /** * @author Jitendra Singh + * @since 4.2 */ public class UsernamePasswordAuthenticationTokenMixinTest extends AbstractMixinTests { diff --git a/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java b/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java index 38852edbf9e..21248853d63 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java @@ -36,6 +36,7 @@ * * @author Jitendra Singh * @see CookieMixin + * @since 4.2 */ public class CookieDeserializer extends JsonDeserializer { diff --git a/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java index ae03001e23a..634027ae72b 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java @@ -29,6 +29,7 @@ * * * @author Jitendra Singh + * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonDeserialize(using = CookieDeserializer.class) diff --git a/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java index 52ddf8de976..9fc4a97a3be 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java @@ -28,6 +28,7 @@ * * * @author Jitendra Singh + * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") public class DefaultCsrfTokenMixin { diff --git a/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java index 6e683488b6c..d78e111455b 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java @@ -38,6 +38,7 @@ * * * @author Jitendra Singh + * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonDeserialize(builder = DefaultSavedRequest.Builder.class) diff --git a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java index 2bc16e737e3..f09aad0f9a1 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java @@ -29,6 +29,7 @@ * * * @author Jitendra Singh + * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) public class WebAuthenticationDetailsMixin { diff --git a/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java b/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java index a2706925384..737161b110c 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java @@ -34,7 +34,8 @@ * mapper.registerModule(new WebJackson2SimpleModule()); * * - * @author Jitendra Singh. + * @author Jitendra Singh + * @since 4.2 */ public class WebJackson2SimpleModule extends SimpleModule { diff --git a/web/src/main/java/org/springframework/security/web/jackson2/package-info.java b/web/src/main/java/org/springframework/security/web/jackson2/package-info.java index 72961dd4570..9bc066de22c 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/package-info.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/package-info.java @@ -15,5 +15,8 @@ */ /** * Mix-in classes to provide Jackson serialization support. + * + * @author Jitendra Singh + * @since 4.2 */ package org.springframework.security.web.jackson2; \ No newline at end of file diff --git a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java index 8a2567e08e7..69a0ab7fa0f 100644 --- a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java +++ b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java @@ -144,6 +144,9 @@ private DefaultSavedRequest(String contextPath, String method, String pathInfo, // ~ Methods // ======================================================================================================== + /** + * @since 4.2 + */ private void addCookies(Cookie[] cookies) { if (cookies != null) { for (Cookie cookie : cookies) { @@ -167,6 +170,9 @@ private void addHeader(String name, String value) { values.add(value); } + /** + * @since 4.2 + */ private void addLocales(Enumeration locales) { while (locales.hasMoreElements()) { Locale locale = locales.nextElement(); @@ -178,6 +184,9 @@ private void addLocale(Locale locale) { locales.add(locale); } + /** + * @since 4.2 + */ private void addParameters(Map parameters) { for (String paramName : parameters.keySet()) { Object paramValues = parameters.get(paramName); @@ -380,6 +389,9 @@ public String toString() { return "DefaultSavedRequest[" + getRedirectUrl() + "]"; } + /** + * @since 4.2 + */ @JsonIgnoreProperties(ignoreUnknown = true) public static class Builder { diff --git a/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java index b2ecac5190d..3702d63ae56 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java @@ -29,6 +29,7 @@ /** * @author Jitendra Singh + * @since 4.2 */ public class CookieMixinTest { diff --git a/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java index a6c10ed53bc..09bfe301db4 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java @@ -33,6 +33,7 @@ /** * @author Jitendra Singh + * @since 4.2 */ @RunWith(MockitoJUnitRunner.class) public class DefaultCsrfTokenMixinTests { diff --git a/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java index 875a310078a..23be5d96964 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java @@ -38,6 +38,7 @@ /** * @author Jitendra Singh + * @since 4.2 */ @RunWith(MockitoJUnitRunner.class) public class DefaultSavedRequestMixinTest { diff --git a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java index 87ae983d026..2820bba0fad 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java @@ -35,6 +35,7 @@ /** * @author Jitendra Singh + * @since 4.2 */ @RunWith(MockitoJUnitRunner.class) public class WebAuthenticationDetailsMixinTest { From 4bc98c6bdacb6ce5e460769ab11e7319458c0ed0 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Tue, 19 Jul 2016 18:04:30 +0530 Subject: [PATCH 45/62] Constructor parameter changed --- .../web/savedrequest/DefaultSavedRequest.java | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java index 69a0ab7fa0f..2a05a4ffefa 100644 --- a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java +++ b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java @@ -126,19 +126,17 @@ public DefaultSavedRequest(HttpServletRequest request, PortResolver portResolver /** * Private constructor invoked through Builder */ - private DefaultSavedRequest(String contextPath, String method, String pathInfo, String queryString, String requestURI, - String requestURL, String scheme, String serverName, String servletPath, int serverPort) { - - this.contextPath = contextPath; - this.method = method; - this.pathInfo = pathInfo; - this.queryString = queryString; - this.requestURI = requestURI; - this.requestURL = requestURL; - this.scheme = scheme; - this.serverName = serverName; - this.servletPath = servletPath; - this.serverPort = serverPort; + private DefaultSavedRequest(Builder builder) { + this.contextPath = builder.contextPath; + this.method = builder.method; + this.pathInfo = builder.pathInfo; + this.queryString = builder.queryString; + this.requestURI = builder.requestURI; + this.requestURL = builder.requestURL; + this.scheme = builder.scheme; + this.serverName = builder.serverName; + this.servletPath = builder.servletPath; + this.serverPort = builder.serverPort; } // ~ Methods @@ -206,13 +204,12 @@ private void addParameter(String name, String[] values) { /** * Determines if the current request matches the DefaultSavedRequest. - *

+ *

* All URL arguments are considered but not cookies, locales, headers or parameters. * - * @param request the actual request to be matched against this one + * @param request the actual request to be matched against this one * @param portResolver used to obtain the server port of the request * @return true if the request is deemed to match this one. - * */ public boolean doesRequestMatch(HttpServletRequest request, PortResolver portResolver) { @@ -374,8 +371,7 @@ private boolean propertyEquals(String log, Object arg1, Object arg2) { } return true; - } - else { + } else { if (logger.isDebugEnabled()) { logger.debug(log + ": arg1=" + arg1 + "; arg2=" + arg2 + " (property not equals)"); @@ -481,10 +477,7 @@ public Builder setServerPort(int serverPort) { } public DefaultSavedRequest build() { - DefaultSavedRequest savedRequest = new DefaultSavedRequest( - this.contextPath, this.method, this.pathInfo, this.queryString, this.requestURI, - this.requestURL, this.scheme, this.serverName, this.servletPath, this.serverPort - ); + DefaultSavedRequest savedRequest = new DefaultSavedRequest(this); savedRequest.addCookies(this.cookies.toArray(new Cookie[]{})); savedRequest.locales.addAll(this.locales); savedRequest.addParameters(this.parameters); From 043459e47bc10bcfc33948b52522232307d8ce81 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Wed, 20 Jul 2016 12:06:23 +0530 Subject: [PATCH 46/62] extractHashKey method moved from AbstractAuthenticationToken to child classes --- .../CasAuthenticationToken.java | 67 +++++++++++-------- .../AbstractAuthenticationToken.java | 21 ++---- .../AnonymousAuthenticationToken.java | 12 ++++ 3 files changed, 54 insertions(+), 46 deletions(-) diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java index c7081de6ea9..5e79e7d7863 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java @@ -50,54 +50,51 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen /** * Constructor. * - * @param key to identify if this object made by a given - * {@link CasAuthenticationProvider} - * @param principal typically the UserDetails object (cannot be null) + * @param key to identify if this object made by a given + * {@link CasAuthenticationProvider} + * @param principal typically the UserDetails object (cannot be null) * @param credentials the service/proxy ticket ID from CAS (cannot be - * null) + * null) * @param authorities the authorities granted to the user (from the - * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot - * be null) + * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot + * be null) * @param userDetails the user details (from the - * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot - * be null) - * @param assertion the assertion returned from the CAS servers. It contains the - * principal and how to obtain a proxy ticket for the user. - * + * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot + * be null) + * @param assertion the assertion returned from the CAS servers. It contains the + * principal and how to obtain a proxy ticket for the user. * @throws IllegalArgumentException if a null was passed */ public CasAuthenticationToken(final String key, final Object principal, - final Object credentials, - final Collection authorities, - final UserDetails userDetails, final Assertion assertion) { + final Object credentials, + final Collection authorities, + final UserDetails userDetails, final Assertion assertion) { this(extractKeyHash(key), principal, credentials, authorities, userDetails, assertion); } /** * Private constructor for Jackson Deserialization support * - * @param keyHash hashCode of provided key to identify if this object made by a given - * {@link CasAuthenticationProvider} - * @param principal typically the UserDetails object (cannot be null) + * @param keyHash hashCode of provided key to identify if this object made by a given + * {@link CasAuthenticationProvider} + * @param principal typically the UserDetails object (cannot be null) * @param credentials the service/proxy ticket ID from CAS (cannot be - * null) + * null) * @param authorities the authorities granted to the user (from the - * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot - * be null) + * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot + * be null) * @param userDetails the user details (from the - * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot - * be null) - * @param assertion the assertion returned from the CAS servers. It contains the - * principal and how to obtain a proxy ticket for the user. - * + * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot + * be null) + * @param assertion the assertion returned from the CAS servers. It contains the + * principal and how to obtain a proxy ticket for the user. * @throws IllegalArgumentException if a null was passed - * * @since 4.2 */ private CasAuthenticationToken(final Integer keyHash, final Object principal, - final Object credentials, - final Collection authorities, - final UserDetails userDetails, final Assertion assertion) { + final Object credentials, + final Collection authorities, + final UserDetails userDetails, final Assertion assertion) { super(authorities); if ((principal == null) @@ -119,6 +116,18 @@ private CasAuthenticationToken(final Integer keyHash, final Object principal, // ~ Methods // ======================================================================================================== + private static Integer extractKeyHash(String key) { + Object value = nullSafeValue(key); + return value.hashCode(); + } + + private static Object nullSafeValue(Object value) { + if (value == null || "".equals(value)) { + throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); + } + return value; + } + public boolean equals(final Object obj) { if (!super.equals(obj)) { return false; diff --git a/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java index 46d08eec30f..360ce593648 100644 --- a/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java @@ -29,7 +29,7 @@ /** * Base class for Authentication objects. - *

+ *

* Implementations which use this class should be immutable. * * @author Ben Alex @@ -40,8 +40,8 @@ public abstract class AbstractAuthenticationToken implements Authentication, // ~ Instance fields // ================================================================================================ - private Object details; private final Collection authorities; + private Object details; private boolean authenticated = false; // ~ Constructors @@ -51,7 +51,7 @@ public abstract class AbstractAuthenticationToken implements Authentication, * Creates a token with the supplied array of authorities. * * @param authorities the collection of GrantedAuthoritys for the principal - * represented by this authentication object. + * represented by this authentication object. */ public AbstractAuthenticationToken(Collection authorities) { if (authorities == null) { @@ -215,23 +215,10 @@ public String toString() { sb.append(authority); } - } - else { + } else { sb.append("Not granted any authorities"); } return sb.toString(); } - - protected static Integer extractKeyHash(String key) { - Object value = nullSafeValue(key); - return value.hashCode(); - } - - protected static Object nullSafeValue(Object value){ - if(value == null || "".equals(value)) { - throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); - } - return value; - } } diff --git a/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java index 8e83f857fe8..59d604d6d9a 100644 --- a/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java @@ -75,6 +75,18 @@ private AnonymousAuthenticationToken(Integer keyHash, Object principal, // ~ Methods // ======================================================================================================== + private static Integer extractKeyHash(String key) { + Object value = nullSafeValue(key); + return value.hashCode(); + } + + private static Object nullSafeValue(Object value) { + if (value == null || "".equals(value)) { + throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); + } + return value; + } + public boolean equals(Object obj) { if (!super.equals(obj)) { return false; From 785a6b91bbed31f6e1cda0648bc08dc81c5c6f00 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Mon, 25 Jul 2016 12:11:43 +0530 Subject: [PATCH 47/62] Json autodetect info updated, fields visibility marked any to ensure serialize properties only --- .../cas/jackson2/AssertionImplMixin.java | 9 ++++----- .../jackson2/AttributePrincipalImplMixin.java | 7 ++++--- .../jackson2/CasAuthenticationTokenMixin.java | 7 +++---- ...2SimpleModule.java => CasJackson2Module.java} | 6 +++--- .../AnonymousAuthenticationTokenMixin.java | 2 ++ .../RememberMeAuthenticationTokenMixin.java | 7 +++---- .../jackson2/SimpleGrantedAuthorityMixin.java | 2 ++ .../security/jackson2/UserMixin.java | 5 +++++ ...UsernamePasswordAuthenticationTokenMixin.java | 2 ++ .../web/jackson2/DefaultCsrfTokenMixin.java | 1 + .../web/jackson2/DefaultSavedRequestMixin.java | 16 +++------------- .../jackson2/WebAuthenticationDetailsMixin.java | 7 ++++--- 12 files changed, 36 insertions(+), 35 deletions(-) rename cas/src/main/java/org/springframework/security/cas/jackson2/{CasJackson2SimpleModule.java => CasJackson2Module.java} (90%) diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java index 468574d1dc4..aeb708fe27c 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java @@ -16,10 +16,7 @@ package org.springframework.security.cas.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; +import com.fasterxml.jackson.annotation.*; import org.jasig.cas.client.authentication.AttributePrincipal; import java.util.Date; @@ -40,7 +37,9 @@ * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) -@JsonIgnoreProperties(value = {"valid"}) +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, + getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE) +@JsonIgnoreProperties(ignoreUnknown = true) public class AssertionImplMixin { /** diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java index e83d59e8172..5112909e8c4 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java @@ -16,9 +16,7 @@ package org.springframework.security.cas.jackson2; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.*; import org.jasig.cas.client.proxy.ProxyRetriever; import java.util.Map; @@ -37,6 +35,9 @@ * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, + isGetterVisibility = JsonAutoDetect.Visibility.NONE) +@JsonIgnoreProperties(ignoreUnknown = true) public class AttributePrincipalImplMixin { /** diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java index 7a607031225..7aa1013460e 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java @@ -16,10 +16,7 @@ package org.springframework.security.cas.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; +import com.fasterxml.jackson.annotation.*; import org.jasig.cas.client.validation.Assertion; import org.springframework.security.cas.authentication.CasAuthenticationProvider; import org.springframework.security.cas.authentication.CasAuthenticationToken; @@ -49,6 +46,8 @@ * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE, + getterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.ANY) @JsonIgnoreProperties(ignoreUnknown = true) public class CasAuthenticationTokenMixin { diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2SimpleModule.java b/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java similarity index 90% rename from cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2SimpleModule.java rename to cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java index 3c38564148f..59e0963da93 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2SimpleModule.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java @@ -35,10 +35,10 @@ * @author Jitendra Singh. * @since 4.2 */ -public class CasJackson2SimpleModule extends SimpleModule { +public class CasJackson2Module extends SimpleModule { - public CasJackson2SimpleModule() { - super(CasJackson2SimpleModule.class.getName(), new Version(1, 0, 0, null, null, null)); + public CasJackson2Module() { + super(CasJackson2Module.class.getName(), new Version(1, 0, 0, null, null, null)); } @Override diff --git a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java index c323235dc23..67296546594 100644 --- a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java @@ -38,6 +38,8 @@ * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE, + getterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.ANY) @JsonIgnoreProperties(ignoreUnknown = true) public class AnonymousAuthenticationTokenMixin { diff --git a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java index 463322c2302..87c4efc076b 100644 --- a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java @@ -16,10 +16,7 @@ package org.springframework.security.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; +import com.fasterxml.jackson.annotation.*; import org.springframework.security.core.GrantedAuthority; import java.util.Collection; @@ -49,6 +46,8 @@ * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, + isGetterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.ANY) @JsonIgnoreProperties(ignoreUnknown = true) public class RememberMeAuthenticationTokenMixin { diff --git a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java index d9fd5551b8c..d08a4895f95 100644 --- a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java @@ -34,6 +34,8 @@ * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, + isGetterVisibility = JsonAutoDetect.Visibility.NONE) @JsonIgnoreProperties(ignoreUnknown = true) public abstract class SimpleGrantedAuthorityMixin { diff --git a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java index 04703c5378b..63104c35b5f 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java @@ -16,6 +16,8 @@ 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; @@ -39,5 +41,8 @@ */ @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) public abstract class UserMixin { } diff --git a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java index 4b985d383a4..d19fa7a01bd 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java @@ -42,6 +42,8 @@ * @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) public abstract class UsernamePasswordAuthenticationTokenMixin { } diff --git a/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java index 9fc4a97a3be..ea4d7baf0a1 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java @@ -31,6 +31,7 @@ * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") +@JsonIgnoreProperties(ignoreUnknown = true) public class DefaultCsrfTokenMixin { /** diff --git a/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java index d78e111455b..3229d2e5a85 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java @@ -26,11 +26,11 @@ import java.util.Map; /** -` * Jackson mixin class to serialize/deserialize {@link DefaultSavedRequest}. This mixin use + * ` * Jackson mixin class to serialize/deserialize {@link DefaultSavedRequest}. This mixin use * {@link org.springframework.security.web.savedrequest.DefaultSavedRequest.Builder} to * deserialized josn.In order to use this mixin class you also need to register * {@link CookieMixin}. - * + *

*

  *     ObjectMapper mapper = new ObjectMapper();
  *     mapper.addMixIn(Cookie.class, CookieMixin.class);
@@ -42,16 +42,6 @@
  */
 @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
 @JsonDeserialize(builder = DefaultSavedRequest.Builder.class)
-@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY)
-@JsonIgnoreProperties(
-		value = {"headerNames", "headerValues", "parameterNames", "redirectUrl"}
-)
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
 public abstract class DefaultSavedRequestMixin {
-
-	/**
-	 * This method will ensure that all the request parameters will must in 'parameters' key.
-	 * @return
-	 */
-	@JsonProperty("parameters")
-	public abstract Map getParameterMap();
 }
diff --git a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java
index f09aad0f9a1..3bd35303f60 100644
--- a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java
+++ b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java
@@ -16,9 +16,7 @@
 
 package org.springframework.security.web.jackson2;
 
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.*;
 
 /**
  * Jackson mixin class to serialize/deserialize {@link org.springframework.security.web.authentication.WebAuthenticationDetails}.
@@ -32,6 +30,9 @@
  * @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)
 public class WebAuthenticationDetailsMixin {
 
 	@JsonCreator

From f3d0649bdd96b1694fe3b37ffdda74872cbb2859 Mon Sep 17 00:00:00 2001
From: Jitendra Singh Bisht 
Date: Mon, 25 Jul 2016 12:13:29 +0530
Subject: [PATCH 48/62] Mixin added for SavedCookie class

---
 .../web/jackson2/SavedCookieMixin.java        | 21 +++++++++++++++++++
 .../web/jackson2/WebJackson2SimpleModule.java |  2 ++
 2 files changed, 23 insertions(+)
 create mode 100644 web/src/main/java/org/springframework/security/web/jackson2/SavedCookieMixin.java

diff --git a/web/src/main/java/org/springframework/security/web/jackson2/SavedCookieMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/SavedCookieMixin.java
new file mode 100644
index 00000000000..b8db7243c92
--- /dev/null
+++ b/web/src/main/java/org/springframework/security/web/jackson2/SavedCookieMixin.java
@@ -0,0 +1,21 @@
+package org.springframework.security.web.jackson2;
+
+import com.fasterxml.jackson.annotation.*;
+
+/**
+ * @author Jitendra Singh.
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY,
+		getterVisibility = JsonAutoDetect.Visibility.NONE)
+@JsonIgnoreProperties(ignoreUnknown = true)
+public abstract class SavedCookieMixin {
+
+	@JsonCreator
+	public 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/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java b/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java
index 737161b110c..5e1e773cfdf 100644
--- a/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java
+++ b/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java
@@ -21,6 +21,7 @@
 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;
 
 import javax.servlet.http.Cookie;
 
@@ -46,6 +47,7 @@ public WebJackson2SimpleModule() {
 	@Override
 	public void setupModule(SetupContext context) {
 		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);

From 257c3bda9432ce1296e26898fdc1e3e73827932e Mon Sep 17 00:00:00 2001
From: Jitendra Singh Bisht 
Date: Mon, 25 Jul 2016 12:14:55 +0530
Subject: [PATCH 49/62] Externalized ObjectMapper configuration and tests
 updated

---
 .../security/jackson2/AbstractMixinTests.java  | 13 +++++++------
 .../AnonymousAuthenticationTokenMixinTest.java | 15 +++------------
 ...RememberMeAuthenticationTokenMixinTest.java | 18 ++++--------------
 .../jackson2/SecurityContextMixinTest.java     | 14 +++-----------
 .../SimpleGrantedAuthorityMixinTest.java       | 16 ++++------------
 .../jackson2/UserDeserializerTests.java        |  7 -------
 6 files changed, 21 insertions(+), 62 deletions(-)

diff --git a/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java
index c9c4cba36e9..4c892802a10 100644
--- a/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java
+++ b/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java
@@ -16,12 +16,10 @@
 
 package org.springframework.security.jackson2;
 
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.annotation.PropertyAccessor;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.runner.RunWith;
 import org.mockito.runners.MockitoJUnitRunner;
+import org.springframework.util.ObjectUtils;
 
 /**
  * @author Jitenra Singh
@@ -30,10 +28,13 @@
 @RunWith(MockitoJUnitRunner.class)
 public abstract class AbstractMixinTests {
 
+	ObjectMapper mapper;
+
 	protected ObjectMapper buildObjectMapper() {
-		ObjectMapper mapper = new ObjectMapper()
-				.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
-		mapper.setVisibilityChecker(mapper.getVisibilityChecker().withVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY));
+		if (ObjectUtils.isEmpty(mapper)) {
+			mapper = new ObjectMapper();
+			SecurityJacksonModules.registerModules(mapper);
+		}
 		return mapper;
 	}
 }
diff --git a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java
index 66c7d301058..ef75837e90d 100644
--- a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java
+++ b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java
@@ -18,12 +18,10 @@
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import org.json.JSONException;
 import org.junit.Test;
 import org.skyscreamer.jsonassert.JSONAssert;
 import org.springframework.security.authentication.AnonymousAuthenticationToken;
-import org.springframework.security.authentication.RememberMeAuthenticationToken;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 
@@ -38,13 +36,6 @@
  */
 public class AnonymousAuthenticationTokenMixinTest extends AbstractMixinTests {
 
-	@Override
-	public ObjectMapper buildObjectMapper() {
-		return super.buildObjectMapper()
-				.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class)
-				.addMixIn(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class);
-	}
-
 	@Test(expected = IllegalArgumentException.class)
 	public void testWithNullAuthorities() throws JsonProcessingException, JSONException {
 		new AnonymousAuthenticationToken("key", "principal", null);
@@ -59,7 +50,7 @@ public void testWithEmptyAuthorities() throws JsonProcessingException, JSONExcep
 	public void serializeAnonymousAuthenticationTokenTest() throws JsonProcessingException, JSONException {
 		String key = "key";
 		String expectedJson = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+
-				"\"principal\": \"user\", \"credentials\": \"\", \"authenticated\": true, \"name\": \"user\", \"keyHash\": "+key.hashCode()+","+
+				"\"principal\": \"user\", \"authenticated\": true, \"keyHash\": "+key.hashCode()+","+
 				"\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}";
 		AnonymousAuthenticationToken token = new AnonymousAuthenticationToken(
 				key, "user", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))
@@ -72,7 +63,7 @@ public void serializeAnonymousAuthenticationTokenTest() throws JsonProcessingExc
 	public void deserializeAnonymousAuthenticationTokenTest() throws IOException {
 		String key = "123456789";
 		String jsonString = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+
-				"\"principal\": \"user\", \"credentials\": \"\", \"authenticated\": true, \"name\": \"user\", \"keyHash\": "+key.hashCode()+","+
+				"\"principal\": \"user\", \"authenticated\": true, \"keyHash\": "+key.hashCode()+","+
 				"\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}";
 		AnonymousAuthenticationToken token = buildObjectMapper().readValue(jsonString, AnonymousAuthenticationToken.class);
 		assertThat(token).isNotNull();
@@ -84,7 +75,7 @@ public void deserializeAnonymousAuthenticationTokenTest() throws IOException {
 	public void deserializeAnonymousAuthenticationTokenWithoutAuthoritiesTest() throws IOException {
 		String key = "123456789";
 		String jsonString = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+
-				"\"principal\": \"user\", \"credentials\": \"\", \"authenticated\": true, \"name\": \"user\", \"keyHash\": "+key.hashCode()+","+
+				"\"principal\": \"user\", \"authenticated\": true, \"keyHash\": "+key.hashCode()+","+
 				"\"authorities\": [\"java.util.ArrayList\", []]}";
 		buildObjectMapper().readValue(jsonString, AnonymousAuthenticationToken.class);
 	}
diff --git a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java
index f8ced739b55..e8c6a6797c1 100644
--- a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java
+++ b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java
@@ -17,7 +17,6 @@
 package org.springframework.security.jackson2;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import org.json.JSONException;
 import org.junit.Test;
 import org.skyscreamer.jsonassert.JSONAssert;
@@ -38,15 +37,6 @@
  */
 public class RememberMeAuthenticationTokenMixinTest extends AbstractMixinTests {
 
-	@Override
-	public ObjectMapper buildObjectMapper() {
-		return super.buildObjectMapper()
-				.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class)
-				.addMixIn(User.class, UserMixin.class)
-				.addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class)
-				.addMixIn(RememberMeAuthenticationToken.class, RememberMeAuthenticationTokenMixin.class);
-	}
-
 	@Test(expected = IllegalArgumentException.class)
 	public void testWithNullPrincipal() throws JsonProcessingException, JSONException {
 		new RememberMeAuthenticationToken("key", null, Collections.emptyList());
@@ -62,7 +52,7 @@ public void serializeRememberMeAuthenticationToken() throws JsonProcessingExcept
 		String key = "rememberMe";
 		RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(key, "user", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")));
 		String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," +
-				"\"keyHash\": "+key.hashCode()+", \"principal\": \"user\", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," +
+				"\"keyHash\": "+key.hashCode()+", \"principal\": \"user\", \"authenticated\": true, \"details\": null," +
 				"\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}";
 		String actualJson = buildObjectMapper().writeValueAsString(token);
 		JSONAssert.assertEquals(expectedJson, actualJson, true);
@@ -74,7 +64,7 @@ public void serializeRememberMeAuthenticationWithUserToken() throws JsonProcessi
 		List authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
 		RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(key, new User("user", "password", authorities), authorities);
 		String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," +
-				"\"keyHash\": "+key.hashCode()+", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," +
+				"\"keyHash\": "+key.hashCode()+", \"authenticated\": true, \"details\": null," +
 				"\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"password\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]},"+
 				"\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}";
 		String actualJson = buildObjectMapper().writeValueAsString(token);
@@ -85,7 +75,7 @@ public void serializeRememberMeAuthenticationWithUserToken() throws JsonProcessi
 	public void deserializeRememberMeAuthenticationToken() throws IOException {
 		String key = "rememberMe";
 		String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," +
-				"\"keyHash\": "+key.hashCode()+", \"principal\": \"user\", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," +
+				"\"keyHash\": "+key.hashCode()+", \"principal\": \"user\", \"authenticated\": true, \"details\": null," +
 				"\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}";
 		RememberMeAuthenticationToken token = buildObjectMapper().readValue(expectedJson, RememberMeAuthenticationToken.class);
 		assertThat(token).isNotNull();
@@ -97,7 +87,7 @@ public void deserializeRememberMeAuthenticationToken() throws IOException {
 	public void deserializeRememberMeAuthenticationTokenWithUserTest() throws IOException {
 		String key = "rememberMe";
 		String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," +
-				"\"keyHash\": "+key.hashCode()+", \"authenticated\": true, \"details\": null, \"name\": \"user\", \"credentials\": \"\"," +
+				"\"keyHash\": "+key.hashCode()+", \"authenticated\": true, \"details\": null," +
 				"\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"password\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]},"+
 				"\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}";
 		RememberMeAuthenticationToken token = buildObjectMapper().readValue(expectedJson, RememberMeAuthenticationToken.class);
diff --git a/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java
index 0761c9a64dd..f1ecd23da71 100644
--- a/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java
+++ b/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java
@@ -17,7 +17,6 @@
 package org.springframework.security.jackson2;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import org.json.JSONException;
 import org.junit.Test;
 import org.skyscreamer.jsonassert.JSONAssert;
@@ -29,7 +28,7 @@
 import java.io.IOException;
 import java.util.Collections;
 
-import static org.assertj.core.api.Assertions.*;
+import static org.assertj.core.api.Assertions.assertThat;
 
 /**
  * @author Jitendra Singh
@@ -37,18 +36,11 @@
  */
 public class SecurityContextMixinTest extends AbstractMixinTests {
 
-	@Override
-	protected ObjectMapper buildObjectMapper() {
-		return super.buildObjectMapper()
-				.addMixIn(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class)
-				.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
-	}
-
 	@Test
 	public void securityContextSerializeTest() throws JsonProcessingException, JSONException {
 		String expectedJson = "{\"@class\": \"org.springframework.security.core.context.SecurityContextImpl\", \"authentication\": " +
 					"{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," +
-						"\"principal\": \"user\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, \"name\": \"user\"," +
+						"\"principal\": \"user\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null," +
 						"\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]" +
 					"}" +
 				"}";
@@ -62,7 +54,7 @@ public void securityContextSerializeTest() throws JsonProcessingException, JSONE
 	public void securityContextDeserializeTest() throws IOException {
 		String contextJson = "{\"@class\": \"org.springframework.security.core.context.SecurityContextImpl\", \"authentication\": " +
 				"{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," +
-					"\"principal\": \"user\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, \"name\": \"user\"," +
+					"\"principal\": \"user\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null," +
 					"\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]" +
 					"}" +
 				"}";
diff --git a/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java
index 8a136d18fde..7fc7d599977 100644
--- a/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java
+++ b/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java
@@ -35,20 +35,12 @@
  * @author Jitendra Singh
  * @since 4.2
  */
-public class SimpleGrantedAuthorityMixinTest {
-
-	ObjectMapper mapper;
-
-	@Before
-	public void setup() {
-		mapper = new ObjectMapper();
-		mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
-	}
+public class SimpleGrantedAuthorityMixinTest extends AbstractMixinTests {
 
 	@Test
 	public void serializeSimpleGrantedAuthorityTest() throws JsonProcessingException, JSONException {
 		SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
-		String serializeJson = mapper.writeValueAsString(authority);
+		String serializeJson = buildObjectMapper().writeValueAsString(authority);
 		String expectedJson = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}";
 		JSONAssert.assertEquals(expectedJson, serializeJson, true);
 	}
@@ -56,7 +48,7 @@ public void serializeSimpleGrantedAuthorityTest() throws JsonProcessingException
 	@Test
 	public void deserializeGrantedAuthorityTest() throws IOException {
 		String json = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}";
-		SimpleGrantedAuthority authority = mapper.readValue(json, SimpleGrantedAuthority.class);
+		SimpleGrantedAuthority authority = buildObjectMapper().readValue(json, SimpleGrantedAuthority.class);
 		assertThat(authority).isNotNull();
 		assertThat(authority.getAuthority()).isNotNull().isEqualTo("ROLE_USER");
 	}
@@ -64,6 +56,6 @@ public void deserializeGrantedAuthorityTest() throws IOException {
 	@Test(expected = JsonMappingException.class)
 	public void deserializeGrantedAuthorityWithoutRoleTest() throws IOException {
 		String json = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\"}";
-		mapper.readValue(json, SimpleGrantedAuthority.class);
+		buildObjectMapper().readValue(json, SimpleGrantedAuthority.class);
 	}
 }
diff --git a/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java b/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java
index 81db18401fa..697f500b5dd 100644
--- a/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java
+++ b/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java
@@ -36,13 +36,6 @@
  */
 public class UserDeserializerTests extends AbstractMixinTests {
 
-	protected ObjectMapper buildObjectMapper() {
-		return super.buildObjectMapper()
-				.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class)
-				.addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class)
-				.addMixIn(User.class, UserMixin.class);
-	}
-
 	@Test
 	public void serializeUserTest() throws JsonProcessingException, JSONException {
 		ObjectMapper mapper = buildObjectMapper();

From a5e7cd896b492d03767339061ad61b2267960d7a Mon Sep 17 00:00:00 2001
From: Jitendra Singh Bisht 
Date: Mon, 25 Jul 2016 12:16:05 +0530
Subject: [PATCH 50/62] Externalized ObjectMapper configuration and updated
 tests in web and cas module

---
 .../CasAuthenticationTokenMixinTest.java      | 21 ++---
 ...ePasswordAuthenticationTokenMixinTest.java | 15 +---
 .../web/savedrequest/DefaultSavedRequest.java | 63 +++++++++++----
 .../web/jackson2/AbstractMixinTests.java      | 41 ++++++++++
 .../web/jackson2/CookieMixinTest.java         |  8 +-
 .../jackson2/DefaultCsrfTokenMixinTests.java  |  3 +-
 .../DefaultSavedRequestMixinTest.java         | 58 +++++++-------
 .../web/jackson2/SavedCookieMixinTests.java   | 80 +++++++++++++++++++
 .../WebAuthenticationDetailsMixinTest.java    |  5 +-
 9 files changed, 219 insertions(+), 75 deletions(-)
 create mode 100644 web/src/test/java/org/springframework/security/web/jackson2/AbstractMixinTests.java
 create mode 100644 web/src/test/java/org/springframework/security/web/jackson2/SavedCookieMixinTests.java

diff --git a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java
index 1b223413f68..258e83a353e 100644
--- a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java
+++ b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java
@@ -17,7 +17,6 @@
 package org.springframework.security.cas.jackson2;
 
 import com.fasterxml.jackson.annotation.JsonAutoDetect;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.annotation.PropertyAccessor;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -33,16 +32,14 @@
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.security.core.userdetails.User;
-import org.springframework.security.jackson2.SimpleGrantedAuthorityMixin;
-import org.springframework.security.jackson2.UnmodifiableSetMixin;
-import org.springframework.security.jackson2.UserMixin;
+import org.springframework.security.jackson2.SecurityJacksonModules;
 
 import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 
-import static org.assertj.core.api.Assertions.*;
+import static org.assertj.core.api.Assertions.assertThat;
 
 /**
  * @author Jitendra Singh
@@ -52,15 +49,9 @@
 public class CasAuthenticationTokenMixinTest {
 
 	ObjectMapper buildObjectMapper() {
-		ObjectMapper mapper = new ObjectMapper()
-				.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
-		mapper.setVisibilityChecker(mapper.getVisibilityChecker().withVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY));
-		mapper.addMixIn(CasAuthenticationToken.class, CasAuthenticationTokenMixin.class)
-				.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class)
-				.addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class)
-				.addMixIn(User.class, UserMixin.class)
-				.addMixIn(AssertionImpl.class, AssertionImplMixin.class)
-				.addMixIn(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class);
+		ObjectMapper mapper = new ObjectMapper();
+		SecurityJacksonModules.registerModules(mapper);
+		mapper.setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.NON_PRIVATE);
 		return mapper;
 	}
 
@@ -89,7 +80,7 @@ public void serializeCasAuthenticationTest() throws JsonProcessingException, JSO
 		String expectedJson = "{\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", \"keyHash\": "+key.hashCode()+"," +
 				"\"principal\": \"user\", \"credentials\": \"pass\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]," +
 				"\"userDetails\": {\"@class\": \"org.springframework.security.core.userdetails.User\",\"username\": \"user\", \"password\": \"pass\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," +
-				"\"authenticated\": true, \"details\": null, \"name\": \"user\"," +
+				"\"authenticated\": true, \"details\": null," +
 				"\"assertion\": {" +
 					"\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", \"principal\": {\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", \"name\": \"assertName\", \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, \"proxyGrantingTicket\": null, \"proxyRetriever\": null}, " +
 					"\"validFromDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"validUntilDate\": [\"java.util.Date\", "+endDate.getTime()+"]," +
diff --git a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java
index ef79f6139bc..cf25e3b2b8d 100644
--- a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java
+++ b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java
@@ -37,20 +37,11 @@
  */
 public class UsernamePasswordAuthenticationTokenMixinTest extends AbstractMixinTests {
 
-	@Override
-	protected ObjectMapper buildObjectMapper() {
-		return super.buildObjectMapper()
-				.addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class)
-				.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class)
-				.addMixIn(User.class, UserMixin.class)
-				.addMixIn(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class);
-	}
-
 	@Test
 	public void serializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws JsonProcessingException, JSONException {
 		String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," +
 				" \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": false, \"details\": null, " +
-				"\"authorities\": [\"java.util.ArrayList\", []], \"name\": \"user1\"}";
+				"\"authorities\": [\"java.util.ArrayList\", []]}";
 		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user1", "password");
 		String serializedJson = buildObjectMapper().writeValueAsString(token);
 		JSONAssert.assertEquals(expectedJson, serializedJson, true);
@@ -60,7 +51,7 @@ public void serializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTest
 	public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws JsonProcessingException, JSONException {
 		String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," +
 				" \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, " +
-				"\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]], \"name\": \"user1\"}";
+				"\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}";
 		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user1", "password", Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));
 		String serializedJson = buildObjectMapper().writeValueAsString(token);
 		JSONAssert.assertEquals(expectedJson, serializedJson, true);
@@ -97,7 +88,7 @@ public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinWithUs
 				"\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": true, \"enabled\": true, " +
 				"\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," +
 				"[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"credentials\": \"pass\"," +
-				"\"details\": null, \"name\": \"user\", \"authenticated\": true," +
+				"\"details\": null, \"authenticated\": true," +
 				"\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}";
 		String actualJson = buildObjectMapper().writeValueAsString(token);
 		JSONAssert.assertEquals(expectedJson, actualJson, true);
diff --git a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java
index 2a05a4ffefa..de59c599a58 100644
--- a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java
+++ b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java
@@ -17,11 +17,13 @@
 package org.springframework.security.web.savedrequest;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.springframework.security.web.PortResolver;
 import org.springframework.security.web.util.UrlUtils;
 import org.springframework.util.Assert;
+import org.springframework.util.ObjectUtils;
 
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
@@ -29,18 +31,18 @@
 
 /**
  * Represents central information from a {@code HttpServletRequest}.
- * 

+ *

* This class is used by * {@link org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter} * and {@link org.springframework.security.web.savedrequest.SavedRequestAwareWrapper} to * reproduce the request after successful authentication. An instance of this class is * stored at the time of an authentication exception by * {@link org.springframework.security.web.access.ExceptionTranslationFilter}. - *

+ *

* IMPLEMENTATION NOTE: It is assumed that this object is accessed only from the * context of a single thread, so no synchronization around internal collection classes is * performed. - *

+ *

* This class is based on code in Apache Tomcat. * * @author Craig McClanahan @@ -186,13 +188,15 @@ private void addLocale(Locale locale) { * @since 4.2 */ private void addParameters(Map parameters) { - for (String paramName : parameters.keySet()) { - Object paramValues = parameters.get(paramName); - if (paramValues instanceof String[]) { - this.addParameter(paramName, (String[]) paramValues); - } else { - if (logger.isWarnEnabled()) { - logger.warn("ServletRequest.getParameterMap() returned non-String array"); + if (!ObjectUtils.isEmpty(parameters)) { + for (String paramName : parameters.keySet()) { + Object paramValues = parameters.get(paramName); + if (paramValues instanceof String[]) { + this.addParameter(paramName, (String[]) paramValues); + } else { + if (logger.isWarnEnabled()) { + logger.warn("ServletRequest.getParameterMap() returned non-String array"); + } } } } @@ -389,9 +393,10 @@ public String toString() { * @since 4.2 */ @JsonIgnoreProperties(ignoreUnknown = true) + @JsonPOJOBuilder(withPrefix = "set") public static class Builder { - private List cookies = null; + private List cookies = null; private List locales = null; private Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); private Map parameters = new TreeMap(); @@ -406,7 +411,7 @@ public static class Builder { private String servletPath; private int serverPort = 80; - public Builder setCookies(List cookies) { + public Builder setCookies(List cookies) { this.cookies = cookies; return this; } @@ -476,15 +481,43 @@ public Builder setServerPort(int serverPort) { return this; } + @Override + public String toString() { + return "Builder{" + + "cookies=" + cookies + + ", locales=" + locales + + ", headers=" + headers + + ", parameters=" + parameters + + ", contextPath='" + contextPath + '\'' + + ", method='" + method + '\'' + + ", pathInfo='" + pathInfo + '\'' + + ", queryString='" + queryString + '\'' + + ", requestURI='" + requestURI + '\'' + + ", requestURL='" + requestURL + '\'' + + ", scheme='" + scheme + '\'' + + ", serverName='" + serverName + '\'' + + ", servletPath='" + servletPath + '\'' + + ", serverPort=" + serverPort + + '}'; + } + public DefaultSavedRequest build() { DefaultSavedRequest savedRequest = new DefaultSavedRequest(this); - savedRequest.addCookies(this.cookies.toArray(new Cookie[]{})); - savedRequest.locales.addAll(this.locales); + System.out.println("Building Default Saved request object"); + System.out.println(this.toString()); + if(!ObjectUtils.isEmpty(this.cookies)) { + for (SavedCookie cookie : this.cookies) { + savedRequest.addCookie(cookie.getCookie()); + } + } + if (!ObjectUtils.isEmpty(this.locales)) + savedRequest.locales.addAll(this.locales); savedRequest.addParameters(this.parameters); this.headers.remove(HEADER_IF_MODIFIED_SINCE); this.headers.remove(HEADER_IF_NONE_MATCH); - savedRequest.headers.putAll(this.headers); + if (!ObjectUtils.isEmpty(this.headers)) + savedRequest.headers.putAll(this.headers); return savedRequest; } } diff --git a/web/src/test/java/org/springframework/security/web/jackson2/AbstractMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/AbstractMixinTests.java new file mode 100644 index 00000000000..34114ae1a08 --- /dev/null +++ b/web/src/test/java/org/springframework/security/web/jackson2/AbstractMixinTests.java @@ -0,0 +1,41 @@ +/* + * 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.jackson2; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.security.jackson2.SecurityJacksonModules; +import org.springframework.util.ObjectUtils; + +/** + * @author Jitenra Singh + * @since 4.2 + */ +@RunWith(MockitoJUnitRunner.class) +public abstract class AbstractMixinTests { + + ObjectMapper mapper; + + protected ObjectMapper buildObjectMapper() { + if (ObjectUtils.isEmpty(mapper)) { + mapper = new ObjectMapper(); + SecurityJacksonModules.registerModules(mapper); + } + return mapper; + } +} diff --git a/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java index 3702d63ae56..520bf0a30e9 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java @@ -21,11 +21,12 @@ import org.json.JSONException; import org.junit.Test; import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.security.jackson2.SecurityJacksonModules; import javax.servlet.http.Cookie; import java.io.IOException; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; /** * @author Jitendra Singh @@ -34,8 +35,9 @@ public class CookieMixinTest { ObjectMapper buildObjectMapper() { - return new ObjectMapper() - .addMixIn(Cookie.class, CookieMixin.class); + ObjectMapper mapper = new ObjectMapper(); + SecurityJacksonModules.registerModules(mapper); + return mapper; } @Test diff --git a/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java index 09bfe301db4..f3e0b6e445c 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java @@ -25,6 +25,7 @@ import org.junit.runner.RunWith; import org.mockito.runners.MockitoJUnitRunner; import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.security.jackson2.SecurityJacksonModules; import org.springframework.security.web.csrf.DefaultCsrfToken; import java.io.IOException; @@ -44,7 +45,7 @@ public class DefaultCsrfTokenMixinTests { @Before public void setup() { objectMapper = new ObjectMapper(); - objectMapper.addMixIn(DefaultCsrfToken.class, DefaultCsrfTokenMixin.class); + SecurityJacksonModules.registerModules(objectMapper); defaultCsrfTokenJson = "{\"@class\": \"org.springframework.security.web.csrf.DefaultCsrfToken\", " + "\"headerName\": \"csrf-header\", \"parameterName\": \"_csrf\", \"token\": \"1\"}"; } diff --git a/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java index 23be5d96964..02263f13665 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java @@ -16,10 +16,7 @@ package org.springframework.security.web.jackson2; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.core.JsonProcessingException; import org.json.JSONException; import org.junit.Test; import org.junit.runner.RunWith; @@ -28,6 +25,7 @@ import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.security.web.PortResolverImpl; import org.springframework.security.web.savedrequest.DefaultSavedRequest; +import org.springframework.security.web.savedrequest.SavedCookie; import javax.servlet.http.Cookie; import java.io.IOException; @@ -41,25 +39,12 @@ * @since 4.2 */ @RunWith(MockitoJUnitRunner.class) -public class DefaultSavedRequestMixinTest { - - ObjectMapper buildObjectMapper() { - ObjectMapper mapper = new ObjectMapper() - .enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY) - .addMixIn(DefaultSavedRequest.class, DefaultSavedRequestMixin.class) - .addMixIn(Cookie.class, CookieMixin.class); - mapper.setVisibilityChecker( - mapper.getVisibilityChecker() - .withVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) - .withVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY) - ); - return mapper; - } +public class DefaultSavedRequestMixinTest extends AbstractMixinTests { @Test public void matchRequestBuildWithConstructorAndBuilder() { DefaultSavedRequest request = new DefaultSavedRequest.Builder() - .setCookies(Collections.singletonList(new Cookie("SESSION", "123456789"))) + .setCookies(Collections.singletonList(new SavedCookie(new Cookie("SESSION", "123456789")))) .setHeaders(Collections.singletonMap("x-auth-token", Collections.singletonList("12"))) .setScheme("http").setRequestURL("http://localhost").setServerName("localhost").setRequestURI("") .setLocales(Collections.singletonList(new Locale("en"))).setContextPath("").setMethod("") @@ -71,6 +56,25 @@ public void matchRequestBuildWithConstructorAndBuilder() { assert request.doesRequestMatch(mockRequest, new PortResolverImpl()); } + @Test + public void expectedSerializeTest() throws JsonProcessingException, JSONException { + MockHttpServletRequest request = new MockHttpServletRequest("POST", "/login"); + request.setServerPort(8080); + request.setContextPath("/app"); + request.setCookies(new Cookie("SESSION", "123456789")); + request.addHeader("x-auth-token", "12"); + + DefaultSavedRequest savedRequest = new DefaultSavedRequest(request, new PortResolverImpl()); + + String actualString = buildObjectMapper().writeValueAsString(savedRequest); + String expectedJson = "{\"@class\":\"org.springframework.security.web.savedrequest.DefaultSavedRequest\",\"contextPath\": \"/app\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.web.savedrequest.SavedCookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"secure\": false, \"version\": 0, \"maxAge\": -1, \"comment\": null, \"domain\": null, \"path\": null}]],\n" + + "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"method\": \"POST\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"/login\", \"requestURL\": \"http://localhost:8080/login\",\n" + + "\"scheme\": \"http\", \"serverName\": \"localhost\", \"serverPort\": 8080, \"servletPath\": \"\", \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + + "\"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}}"; + JSONAssert.assertEquals(expectedJson, actualString, true); + } + + @Test public void serializeDefaultRequestBuildWithConstructorTest() throws IOException, JSONException { MockHttpServletRequest request = new MockHttpServletRequest(); @@ -78,7 +82,7 @@ public void serializeDefaultRequestBuildWithConstructorTest() throws IOException request.addHeader("x-auth-token", "12"); String expectedJsonString = "{" + - "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}]]," + + "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.web.savedrequest.SavedCookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"domain\": null}]]," + "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ @@ -90,14 +94,14 @@ public void serializeDefaultRequestBuildWithConstructorTest() throws IOException @Test public void serializeDefaultRequestBuildWithBuilderTest() throws IOException, JSONException { DefaultSavedRequest request = new DefaultSavedRequest.Builder() - .setCookies(Collections.singletonList(new Cookie("SESSION", "123456789"))) + .setCookies(Collections.singletonList(new SavedCookie(new Cookie("SESSION", "123456789")))) .setHeaders(Collections.singletonMap("x-auth-token", Collections.singletonList("12"))) .setScheme("http").setRequestURL("http://localhost").setServerName("localhost").setRequestURI("") .setLocales(Collections.singletonList(new Locale("en"))).setContextPath("").setMethod("") .setServletPath("").build(); String expectedJsonString = "{" + - "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}]]," + + "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.web.savedrequest.SavedCookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"domain\": null}]]," + "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ @@ -109,12 +113,12 @@ public void serializeDefaultRequestBuildWithBuilderTest() throws IOException, JS @Test public void deserializeDefaultSavedRequest() throws IOException { String jsonString = "{" + - "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}]]," + - "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + - "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + - "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ + "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.web.savedrequest.SavedCookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}]]," + + "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + + "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + + "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80" + "}"; - DefaultSavedRequest request = buildObjectMapper().readValue(jsonString, DefaultSavedRequest.class); + DefaultSavedRequest request = (DefaultSavedRequest) buildObjectMapper().readValue(jsonString, Object.class); assertThat(request).isNotNull(); assertThat(request.getCookies()).hasSize(1); assertThat(request.getLocales()).hasSize(1).contains(new Locale("en")); diff --git a/web/src/test/java/org/springframework/security/web/jackson2/SavedCookieMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/SavedCookieMixinTests.java new file mode 100644 index 00000000000..8dc8ffd3336 --- /dev/null +++ b/web/src/test/java/org/springframework/security/web/jackson2/SavedCookieMixinTests.java @@ -0,0 +1,80 @@ +package org.springframework.security.web.jackson2; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.json.JSONException; +import org.junit.Before; +import org.junit.Test; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.security.web.savedrequest.SavedCookie; + +import javax.servlet.http.Cookie; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Jitendra Singh. + */ +public class SavedCookieMixinTests extends AbstractMixinTests { + + private String expectedSavedCookieJson; + + @Before + public void setup() { + expectedSavedCookieJson = "{\"@class\": \"org.springframework.security.web.savedrequest.SavedCookie\", " + + "\"name\": \"session\", \"value\": \"123456\", \"comment\": null, \"domain\": null, \"maxAge\": -1, " + + "\"path\": null, \"secure\": false, \"version\": 0}"; + } + + + @Test + public void serializeWithDefaultConfigurationTest() throws JsonProcessingException, JSONException { + SavedCookie savedCookie = new SavedCookie(new Cookie("session", "123456")); + String actualJson = buildObjectMapper().writeValueAsString(savedCookie); + JSONAssert.assertEquals(expectedSavedCookieJson, actualJson, true); + } + + @Test + public void serializeWithOverrideConfigurationTest() throws JsonProcessingException, JSONException { + SavedCookie savedCookie = new SavedCookie(new Cookie("session", "123456")); + ObjectMapper mapper = buildObjectMapper(); + mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.PUBLIC_ONLY) + .setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY); + String actualJson = mapper.writeValueAsString(savedCookie); + JSONAssert.assertEquals(expectedSavedCookieJson, actualJson, true); + } + + @Test + public void serializeSavedCookieWithList() throws JsonProcessingException, JSONException { + List savedCookies = new ArrayList(); + savedCookies.add(new SavedCookie(new Cookie("session", "123456"))); + String expectedJson = String.format("[\"java.util.ArrayList\", [%s]]", expectedSavedCookieJson); + String actualJson = buildObjectMapper().writeValueAsString(savedCookies); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } + + @Test + public void deserializeSavedCookieWithList() throws IOException, JSONException { + String expectedJson = String.format("[\"java.util.ArrayList\", [%s]]", expectedSavedCookieJson); + List savedCookies = (List)buildObjectMapper().readValue(expectedJson, Object.class); + assertThat(savedCookies).isNotNull().hasSize(1); + assertThat(savedCookies.get(0).getName()).isEqualTo("session"); + assertThat(savedCookies.get(0).getValue()).isEqualTo("123456"); + } + + @Test + public void deserializeSavedCookieJsonTest() throws IOException { + SavedCookie savedCookie = (SavedCookie) buildObjectMapper().readValue(expectedSavedCookieJson, Object.class); + assertThat(savedCookie).isNotNull(); + assertThat(savedCookie.getName()).isEqualTo("session"); + assertThat(savedCookie.getValue()).isEqualTo("123456"); + assertThat(savedCookie.isSecure()).isEqualTo(false); + assertThat(savedCookie.getVersion()).isEqualTo(0); + assertThat(savedCookie.getComment()).isNull(); + } +} diff --git a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java index 2820bba0fad..53ebee6e41d 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java @@ -29,6 +29,7 @@ import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpSession; +import org.springframework.security.jackson2.SecurityJacksonModules; import org.springframework.security.web.authentication.WebAuthenticationDetails; import static org.assertj.core.api.Assertions.assertThat; @@ -44,8 +45,8 @@ public class WebAuthenticationDetailsMixinTest { @Before public void setup() { - this.mapper = new ObjectMapper().addMixIn(WebAuthenticationDetails.class, - WebAuthenticationDetailsMixin.class); + this.mapper = new ObjectMapper(); + SecurityJacksonModules.registerModules(mapper); } @Test From 1f78c7867ae3e9fd80f1eb52be0def3bb28c2006 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Mon, 25 Jul 2016 12:20:29 +0530 Subject: [PATCH 51/62] SecurityJacksonModules class added to auto register spring security mixins/modules --- .../jackson2/SecurityJacksonModules.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java diff --git a/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java b/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java new file mode 100644 index 00000000000..3f7b0744f4c --- /dev/null +++ b/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java @@ -0,0 +1,53 @@ +package org.springframework.security.jackson2; + +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.databind.Module; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.util.ClassUtils; +import org.springframework.util.ObjectUtils; + +/** + * @author Jitendra Singh. + * @Since 4.2 + */ +public final class SecurityJacksonModules { + + private static final Log logger = LogFactory.getLog(SecurityJacksonModules.class); + + private SecurityJacksonModules() { + } + + private static void enableDefaultTyping(ObjectMapper mapper) { + TypeResolverBuilder typeBuilder = mapper.getDeserializationConfig().getDefaultTyper(null); + if (ObjectUtils.isEmpty(typeBuilder)) { + mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); + } + } + + private static void findAndRegisterSecurityModuleClass(ObjectMapper mapper, String className) { + try { + logger.debug("Loading module " + className); + Class casModuleClass = (Class) ClassUtils.forName(className, ClassUtils.getDefaultClassLoader()); + if (!ObjectUtils.isEmpty(casModuleClass)) { + logger.debug("Loaded module " + className + ", now registering"); + mapper.registerModule(casModuleClass.newInstance()); + } + } catch (ClassNotFoundException e) { + logger.warn("Module class not found : "+e.getMessage()); + } catch (InstantiationException e) { + logger.error(e.getMessage()); + } catch (IllegalAccessException e) { + logger.error(e.getMessage()); + } + } + + public static void registerModules(ObjectMapper mapper) { + enableDefaultTyping(mapper); + mapper.registerModule(new CoreJackson2Module()); + findAndRegisterSecurityModuleClass(mapper, "org.springframework.security.cas.jackson2.CasJackson2Module"); + findAndRegisterSecurityModuleClass(mapper, "org.springframework.security.web.jackson2.WebJackson2Module"); + } +} From 625282b72535551f39ffa0dd227d876f3cb395d8 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Mon, 25 Jul 2016 12:20:36 +0530 Subject: [PATCH 52/62] Naming convention corrected for security module classes --- ...oreJackson2SimpleModule.java => CoreJackson2Module.java} | 6 +++--- ...{WebJackson2SimpleModule.java => WebJackson2Module.java} | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) rename core/src/main/java/org/springframework/security/jackson2/{CoreJackson2SimpleModule.java => CoreJackson2Module.java} (92%) rename web/src/main/java/org/springframework/security/web/jackson2/{WebJackson2SimpleModule.java => WebJackson2Module.java} (91%) diff --git a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java similarity index 92% rename from core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java rename to core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java index bddee1839ed..a9448d6e7e9 100644 --- a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2SimpleModule.java +++ b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java @@ -40,10 +40,10 @@ * @author Jitendra Singh. * @since 4.2 */ -public class CoreJackson2SimpleModule extends SimpleModule { +public class CoreJackson2Module extends SimpleModule { - public CoreJackson2SimpleModule() { - super(CoreJackson2SimpleModule.class.getName(), new Version(1, 0, 0, null, null, null)); + public CoreJackson2Module() { + super(CoreJackson2Module.class.getName(), new Version(1, 0, 0, null, null, null)); } @Override diff --git a/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java b/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2Module.java similarity index 91% rename from web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java rename to web/src/main/java/org/springframework/security/web/jackson2/WebJackson2Module.java index 5e1e773cfdf..d591993546d 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2SimpleModule.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2Module.java @@ -38,10 +38,10 @@ * @author Jitendra Singh * @since 4.2 */ -public class WebJackson2SimpleModule extends SimpleModule { +public class WebJackson2Module extends SimpleModule { - public WebJackson2SimpleModule() { - super(WebJackson2SimpleModule.class.getName(), new Version(1, 0, 0, null, null, null)); + public WebJackson2Module() { + super(WebJackson2Module.class.getName(), new Version(1, 0, 0, null, null, null)); } @Override From 40eedcfaa66734f033594d14bb7748dbfff1e69b Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Mon, 25 Jul 2016 12:23:05 +0530 Subject: [PATCH 53/62] test classes renamed as per project's naming convention --- ...okenMixinTest.java => CasAuthenticationTokenMixinTests.java} | 2 +- ...xinTest.java => AnonymousAuthenticationTokenMixinTests.java} | 2 +- ...inTest.java => RememberMeAuthenticationTokenMixinTests.java} | 2 +- ...rityContextMixinTest.java => SecurityContextMixinTests.java} | 2 +- ...rityMixinTest.java => SimpleGrantedAuthorityMixinTests.java} | 2 +- ....java => UsernamePasswordAuthenticationTokenMixinTests.java} | 2 +- .../jackson2/{CookieMixinTest.java => CookieMixinTests.java} | 2 +- ...RequestMixinTest.java => DefaultSavedRequestMixinTests.java} | 2 +- ...lsMixinTest.java => WebAuthenticationDetailsMixinTests.java} | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) rename cas/src/test/java/org/springframework/security/cas/jackson2/{CasAuthenticationTokenMixinTest.java => CasAuthenticationTokenMixinTests.java} (99%) rename core/src/test/java/org/springframework/security/jackson2/{AnonymousAuthenticationTokenMixinTest.java => AnonymousAuthenticationTokenMixinTests.java} (97%) rename core/src/test/java/org/springframework/security/jackson2/{RememberMeAuthenticationTokenMixinTest.java => RememberMeAuthenticationTokenMixinTests.java} (98%) rename core/src/test/java/org/springframework/security/jackson2/{SecurityContextMixinTest.java => SecurityContextMixinTests.java} (98%) rename core/src/test/java/org/springframework/security/jackson2/{SimpleGrantedAuthorityMixinTest.java => SimpleGrantedAuthorityMixinTests.java} (97%) rename core/src/test/java/org/springframework/security/jackson2/{UsernamePasswordAuthenticationTokenMixinTest.java => UsernamePasswordAuthenticationTokenMixinTests.java} (98%) rename web/src/test/java/org/springframework/security/web/jackson2/{CookieMixinTest.java => CookieMixinTests.java} (98%) rename web/src/test/java/org/springframework/security/web/jackson2/{DefaultSavedRequestMixinTest.java => DefaultSavedRequestMixinTests.java} (99%) rename web/src/test/java/org/springframework/security/web/jackson2/{WebAuthenticationDetailsMixinTest.java => WebAuthenticationDetailsMixinTests.java} (98%) diff --git a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java similarity index 99% rename from cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java rename to cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java index 258e83a353e..1dd8763e742 100644 --- a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTest.java +++ b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java @@ -46,7 +46,7 @@ * @since 4.2 */ @RunWith(MockitoJUnitRunner.class) -public class CasAuthenticationTokenMixinTest { +public class CasAuthenticationTokenMixinTests { ObjectMapper buildObjectMapper() { ObjectMapper mapper = new ObjectMapper(); diff --git a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java similarity index 97% rename from core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java rename to core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java index ef75837e90d..61d1bbd072d 100644 --- a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java @@ -34,7 +34,7 @@ * @author Jitendra Singh * @since 4.2 */ -public class AnonymousAuthenticationTokenMixinTest extends AbstractMixinTests { +public class AnonymousAuthenticationTokenMixinTests extends AbstractMixinTests { @Test(expected = IllegalArgumentException.class) public void testWithNullAuthorities() throws JsonProcessingException, JSONException { diff --git a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java similarity index 98% rename from core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java rename to core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java index e8c6a6797c1..2790cdc9f01 100644 --- a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java @@ -35,7 +35,7 @@ * @author Jitendra Singh * @since 4.2 */ -public class RememberMeAuthenticationTokenMixinTest extends AbstractMixinTests { +public class RememberMeAuthenticationTokenMixinTests extends AbstractMixinTests { @Test(expected = IllegalArgumentException.class) public void testWithNullPrincipal() throws JsonProcessingException, JSONException { diff --git a/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTests.java similarity index 98% rename from core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java rename to core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTests.java index f1ecd23da71..5300d33c53c 100644 --- a/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTests.java @@ -34,7 +34,7 @@ * @author Jitendra Singh * @since 4.2 */ -public class SecurityContextMixinTest extends AbstractMixinTests { +public class SecurityContextMixinTests extends AbstractMixinTests { @Test public void securityContextSerializeTest() throws JsonProcessingException, JSONException { diff --git a/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTests.java similarity index 97% rename from core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java rename to core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTests.java index 7fc7d599977..9971e9d632a 100644 --- a/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTests.java @@ -35,7 +35,7 @@ * @author Jitendra Singh * @since 4.2 */ -public class SimpleGrantedAuthorityMixinTest extends AbstractMixinTests { +public class SimpleGrantedAuthorityMixinTests extends AbstractMixinTests { @Test public void serializeSimpleGrantedAuthorityTest() throws JsonProcessingException, JSONException { diff --git a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java similarity index 98% rename from core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java rename to core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java index cf25e3b2b8d..52da33d1d50 100644 --- a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTest.java +++ b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java @@ -35,7 +35,7 @@ * @author Jitendra Singh * @since 4.2 */ -public class UsernamePasswordAuthenticationTokenMixinTest extends AbstractMixinTests { +public class UsernamePasswordAuthenticationTokenMixinTests extends AbstractMixinTests { @Test public void serializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws JsonProcessingException, JSONException { diff --git a/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTests.java similarity index 98% rename from web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java rename to web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTests.java index 520bf0a30e9..5454a94293c 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTest.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTests.java @@ -32,7 +32,7 @@ * @author Jitendra Singh * @since 4.2 */ -public class CookieMixinTest { +public class CookieMixinTests { ObjectMapper buildObjectMapper() { ObjectMapper mapper = new ObjectMapper(); diff --git a/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTests.java similarity index 99% rename from web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java rename to web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTests.java index 02263f13665..889f51a1018 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTest.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTests.java @@ -39,7 +39,7 @@ * @since 4.2 */ @RunWith(MockitoJUnitRunner.class) -public class DefaultSavedRequestMixinTest extends AbstractMixinTests { +public class DefaultSavedRequestMixinTests extends AbstractMixinTests { @Test public void matchRequestBuildWithConstructorAndBuilder() { diff --git a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java similarity index 98% rename from web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java rename to web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java index 53ebee6e41d..0b18812f64f 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTest.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java @@ -39,7 +39,7 @@ * @since 4.2 */ @RunWith(MockitoJUnitRunner.class) -public class WebAuthenticationDetailsMixinTest { +public class WebAuthenticationDetailsMixinTests { ObjectMapper mapper; From 4c84918952f4b95f3318df998b5afb4dcf58296d Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Mon, 25 Jul 2016 14:34:17 +0530 Subject: [PATCH 54/62] tests added when eraseCredential() invoked --- .../CasAuthenticationTokenMixinTests.java | 44 ++++++++++++++----- ...nonymousAuthenticationTokenMixinTests.java | 19 ++++++++ ...memberMeAuthenticationTokenMixinTests.java | 14 ++++++ ...PasswordAuthenticationTokenMixinTests.java | 16 +++++++ 4 files changed, 81 insertions(+), 12 deletions(-) diff --git a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java index 1dd8763e742..2b61c4f852c 100644 --- a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java +++ b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java @@ -48,6 +48,10 @@ @RunWith(MockitoJUnitRunner.class) public class CasAuthenticationTokenMixinTests { + Date startDate = new Date(); + Date endDate = new Date(); + private String key = "casKey"; + ObjectMapper buildObjectMapper() { ObjectMapper mapper = new ObjectMapper(); SecurityJacksonModules.registerModules(mapper); @@ -55,6 +59,13 @@ ObjectMapper buildObjectMapper() { return mapper; } + private CasAuthenticationToken createCasAuthenticationToken(Object principal, Object credentials) { + Collection authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); + Assertion assertion = new AssertionImpl(new AttributePrincipalImpl("assertName"), startDate, endDate, startDate, Collections.emptyMap()); + return new CasAuthenticationToken(key, principal, credentials, authorities, + new User("user", "pass", authorities), assertion); + } + @Test(expected = IllegalArgumentException.class) public void nullKeyTest() { new CasAuthenticationToken(null, "user", "pass", Collections.emptyList(), @@ -69,14 +80,7 @@ public void blankKeyTest() { @Test public void serializeCasAuthenticationTest() throws JsonProcessingException, JSONException { - String key = "casKey"; - Date startDate = new Date(); - Date endDate = new Date(); - Collection authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); - Assertion assertion = new AssertionImpl(new AttributePrincipalImpl("assertName"), startDate, endDate, startDate, Collections.emptyMap()); - CasAuthenticationToken token = new CasAuthenticationToken(key, "user", "pass", authorities, - new User("user", "pass", authorities), assertion); - + CasAuthenticationToken token = createCasAuthenticationToken("user", "pass"); String expectedJson = "{\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", \"keyHash\": "+key.hashCode()+"," + "\"principal\": \"user\", \"credentials\": \"pass\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]," + "\"userDetails\": {\"@class\": \"org.springframework.security.core.userdetails.User\",\"username\": \"user\", \"password\": \"pass\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," + @@ -91,11 +95,27 @@ public void serializeCasAuthenticationTest() throws JsonProcessingException, JSO } @Test - public void deserializeCasAuthenticationTest() throws IOException, JSONException { - String key = "casKey"; - Date startDate = new Date(); - Date endDate = new Date(); + public void serializeCasAuthenticationTestAfterEraseCredentialInvoked() throws JsonProcessingException, JSONException { + User user = new User("username", "password", Collections.singletonList(new SimpleGrantedAuthority("USER"))); + CasAuthenticationToken token = createCasAuthenticationToken(user, "password"); + String expectedJson = "{\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", \"keyHash\": "+key.hashCode()+"," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"username\", \"password\": null, \"accountNonExpired\": true, \"enabled\": true," + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + + "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"USER\"}]]}, \"credentials\": \"password\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]," + + "\"userDetails\": {\"@class\": \"org.springframework.security.core.userdetails.User\",\"username\": \"user\", \"password\": \"pass\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," + + "\"authenticated\": true, \"details\": null," + + "\"assertion\": {" + + "\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", \"principal\": {\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", \"name\": \"assertName\", \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, \"proxyGrantingTicket\": null, \"proxyRetriever\": null}, " + + "\"validFromDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"validUntilDate\": [\"java.util.Date\", "+endDate.getTime()+"]," + + "\"authenticationDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" + + "}}"; + token.eraseCredentials(); + String actualJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } + @Test + public void deserializeCasAuthenticationTest() throws IOException, JSONException { String expectedJson = "{\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", \"keyHash\": "+key.hashCode()+"," + "\"principal\": \"user\", \"credentials\": \"pass\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]," + "\"userDetails\": {\"@class\": \"org.springframework.security.core.userdetails.User\",\"username\": \"user\", \"password\": \"pass\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," + diff --git a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java index 61d1bbd072d..5575a98ca3b 100644 --- a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java @@ -24,6 +24,7 @@ import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; import java.io.IOException; import java.util.Collections; @@ -79,4 +80,22 @@ public void deserializeAnonymousAuthenticationTokenWithoutAuthoritiesTest() thro "\"authorities\": [\"java.util.ArrayList\", []]}"; buildObjectMapper().readValue(jsonString, AnonymousAuthenticationToken.class); } + + @Test + public void serializeAnonymousAuthenticationTokenMixinAfterEraseCredentialTest() throws JsonProcessingException, JSONException { + String key = "key"; + GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); + User user = new User("user", "password", Collections.singleton(authority)); + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+ + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": null, \"accountNonExpired\": true, \"enabled\": true, " + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + + "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"authenticated\": true, \"keyHash\": "+key.hashCode()+","+ + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + AnonymousAuthenticationToken token = new AnonymousAuthenticationToken( + key, user, Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")) + ); + token.eraseCredentials(); + String actualJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } } diff --git a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java index 2790cdc9f01..9ecd3f1cec5 100644 --- a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java @@ -71,6 +71,20 @@ public void serializeRememberMeAuthenticationWithUserToken() throws JsonProcessi JSONAssert.assertEquals(expectedJson, actualJson, true); } + @Test + public void serializeRememberMeAuthenticationWithUserTokenAfterEraseCredential() throws JsonProcessingException, JSONException { + String key = "rememberMe"; + List authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + + "\"keyHash\": "+key.hashCode()+", \"authenticated\": true, \"details\": null," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": null, \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]},"+ + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(key, new User("user", "password", authorities), authorities); + token.eraseCredentials(); + String actualJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } + @Test public void deserializeRememberMeAuthenticationToken() throws IOException { String key = "rememberMe"; diff --git a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java index 52da33d1d50..47ecc78937c 100644 --- a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java @@ -110,4 +110,20 @@ public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenWithUserT assertThat(token.isAuthenticated()).isEqualTo(true); assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); } + + @Test + public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinAfterEraseCredentialInvoked() throws JsonProcessingException, JSONException { + GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); + User user = new User("user", "password", Collections.singleton(authority)); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, "password", Collections.singleton(authority)); + String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": null, \"accountNonExpired\": true, \"enabled\": true, " + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + + "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"credentials\": null," + + "\"details\": null, \"authenticated\": true," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + token.eraseCredentials(); + String actualJson = buildObjectMapper().writeValueAsString(token); + JSONAssert.assertEquals(expectedJson, actualJson, true); + } } From 74f48f1794168fea2fe42f151b8cab9e4bf9b14e Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Mon, 25 Jul 2016 23:16:15 +0530 Subject: [PATCH 55/62] tests refactored --- .../CasAuthenticationTokenMixinTests.java | 85 ++++++++----------- .../security/jackson2/AbstractMixinTests.java | 12 +++ ...nonymousAuthenticationTokenMixinTests.java | 44 +++++----- ...memberMeAuthenticationTokenMixinTests.java | 65 ++++++-------- .../jackson2/SecurityContextMixinTests.java | 27 +++--- .../SimpleGrantedAuthorityMixinTests.java | 8 +- .../jackson2/UserDeserializerTests.java | 29 ++++--- ...PasswordAuthenticationTokenMixinTests.java | 66 ++++++-------- .../web/jackson2/CookieMixinTests.java | 11 ++- .../DefaultSavedRequestMixinTests.java | 53 +++--------- .../WebAuthenticationDetailsMixinTests.java | 15 ++-- 11 files changed, 172 insertions(+), 243 deletions(-) diff --git a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java index 2b61c4f852c..87262bd0862 100644 --- a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java +++ b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java @@ -16,8 +16,6 @@ package org.springframework.security.cas.jackson2; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.jasig.cas.client.authentication.AttributePrincipalImpl; @@ -48,88 +46,73 @@ @RunWith(MockitoJUnitRunner.class) public class CasAuthenticationTokenMixinTests { + private final String KEY = "casKey"; + private final String PASSWORD = "pass"; Date startDate = new Date(); Date endDate = new Date(); - private String key = "casKey"; + String expectedJson = "{\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", \"keyHash\": " + KEY.hashCode() + "," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"username\", \"password\": %s, \"accountNonExpired\": true, \"enabled\": true," + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + + "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"USER\"}]]}, \"credentials\": \"" + PASSWORD + "\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]," + + "\"userDetails\": {\"@class\": \"org.springframework.security.core.userdetails.User\",\"username\": \"user\", \"password\": \"" + PASSWORD + "\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," + + "\"authenticated\": true, \"details\": null," + + "\"assertion\": {" + + "\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", \"principal\": {\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", \"name\": \"assertName\", \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, \"proxyGrantingTicket\": null, \"proxyRetriever\": null}, " + + "\"validFromDate\": [\"java.util.Date\", " + startDate.getTime() + "], \"validUntilDate\": [\"java.util.Date\", " + endDate.getTime() + "]," + + "\"authenticationDate\": [\"java.util.Date\", " + startDate.getTime() + "], \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" + + "}}"; + + private CasAuthenticationToken createCasAuthenticationToken() { + User principal = new User("username", PASSWORD, Collections.singletonList(new SimpleGrantedAuthority("USER"))); + Collection authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); + Assertion assertion = new AssertionImpl(new AttributePrincipalImpl("assertName"), startDate, endDate, startDate, Collections.emptyMap()); + return new CasAuthenticationToken(KEY, principal, principal.getPassword(), authorities, + new User("user", PASSWORD, authorities), assertion); + } ObjectMapper buildObjectMapper() { ObjectMapper mapper = new ObjectMapper(); SecurityJacksonModules.registerModules(mapper); - mapper.setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.NON_PRIVATE); return mapper; } - private CasAuthenticationToken createCasAuthenticationToken(Object principal, Object credentials) { - Collection authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); - Assertion assertion = new AssertionImpl(new AttributePrincipalImpl("assertName"), startDate, endDate, startDate, Collections.emptyMap()); - return new CasAuthenticationToken(key, principal, credentials, authorities, - new User("user", "pass", authorities), assertion); - } - @Test(expected = IllegalArgumentException.class) public void nullKeyTest() { - new CasAuthenticationToken(null, "user", "pass", Collections.emptyList(), - new User("user", "pass", Collections.emptyList()), null); + new CasAuthenticationToken(null, "user", PASSWORD, Collections.emptyList(), + new User("user", PASSWORD, Collections.emptyList()), null); } @Test(expected = IllegalArgumentException.class) public void blankKeyTest() { - new CasAuthenticationToken("", "user", "pass", Collections.emptyList(), - new User("user", "pass", Collections.emptyList()), null); + new CasAuthenticationToken("", "user", PASSWORD, Collections.emptyList(), + new User("user", PASSWORD, Collections.emptyList()), null); } @Test public void serializeCasAuthenticationTest() throws JsonProcessingException, JSONException { - CasAuthenticationToken token = createCasAuthenticationToken("user", "pass"); - String expectedJson = "{\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", \"keyHash\": "+key.hashCode()+"," + - "\"principal\": \"user\", \"credentials\": \"pass\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]," + - "\"userDetails\": {\"@class\": \"org.springframework.security.core.userdetails.User\",\"username\": \"user\", \"password\": \"pass\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," + - "\"authenticated\": true, \"details\": null," + - "\"assertion\": {" + - "\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", \"principal\": {\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", \"name\": \"assertName\", \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, \"proxyGrantingTicket\": null, \"proxyRetriever\": null}, " + - "\"validFromDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"validUntilDate\": [\"java.util.Date\", "+endDate.getTime()+"]," + - "\"authenticationDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" + - "}}"; + CasAuthenticationToken token = createCasAuthenticationToken(); String actualJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, actualJson, true); + JSONAssert.assertEquals(String.format(expectedJson, "\"" + PASSWORD + "\""), actualJson, true); } @Test public void serializeCasAuthenticationTestAfterEraseCredentialInvoked() throws JsonProcessingException, JSONException { - User user = new User("username", "password", Collections.singletonList(new SimpleGrantedAuthority("USER"))); - CasAuthenticationToken token = createCasAuthenticationToken(user, "password"); - String expectedJson = "{\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", \"keyHash\": "+key.hashCode()+"," + - "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"username\", \"password\": null, \"accountNonExpired\": true, \"enabled\": true," + - "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + - "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"USER\"}]]}, \"credentials\": \"password\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]," + - "\"userDetails\": {\"@class\": \"org.springframework.security.core.userdetails.User\",\"username\": \"user\", \"password\": \"pass\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," + - "\"authenticated\": true, \"details\": null," + - "\"assertion\": {" + - "\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", \"principal\": {\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", \"name\": \"assertName\", \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, \"proxyGrantingTicket\": null, \"proxyRetriever\": null}, " + - "\"validFromDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"validUntilDate\": [\"java.util.Date\", "+endDate.getTime()+"]," + - "\"authenticationDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" + - "}}"; + CasAuthenticationToken token = createCasAuthenticationToken(); token.eraseCredentials(); String actualJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, actualJson, true); + JSONAssert.assertEquals(String.format(expectedJson, "null"), actualJson, true); } @Test public void deserializeCasAuthenticationTest() throws IOException, JSONException { - String expectedJson = "{\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", \"keyHash\": "+key.hashCode()+"," + - "\"principal\": \"user\", \"credentials\": \"pass\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]," + - "\"userDetails\": {\"@class\": \"org.springframework.security.core.userdetails.User\",\"username\": \"user\", \"password\": \"pass\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," + - "\"authenticated\": true, \"details\": null, \"name\": \"user\"," + - "\"assertion\": {" + - "\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", \"principal\": {\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", \"name\": \"assertName\", \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, \"proxyGrantingTicket\": null, \"proxyRetriever\": null}, " + - "\"validFromDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"validUntilDate\": [\"java.util.Date\", "+endDate.getTime()+"]," + - "\"authenticationDate\": [\"java.util.Date\", "+startDate.getTime()+"], \"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" + - "}}"; - CasAuthenticationToken token = buildObjectMapper().readValue(expectedJson, CasAuthenticationToken.class); + CasAuthenticationToken token = buildObjectMapper().readValue(String.format(expectedJson, "\"" + PASSWORD + "\""), CasAuthenticationToken.class); assertThat(token).isNotNull(); + assertThat(token.getPrincipal()).isNotNull().isInstanceOf(User.class); + assertThat(((User) token.getPrincipal()).getUsername()).isEqualTo("username"); + assertThat(((User) token.getPrincipal()).getPassword()).isEqualTo(PASSWORD); assertThat(token.getUserDetails()).isNotNull().isInstanceOf(User.class); assertThat(token.getAssertion()).isNotNull().isInstanceOf(AssertionImpl.class); - assertThat(token.getKeyHash()).isEqualTo(key.hashCode()); + assertThat(token.getKeyHash()).isEqualTo(KEY.hashCode()); assertThat(token.getUserDetails().getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); assertThat(token.getAssertion().getAuthenticationDate()).isEqualTo(startDate); assertThat(token.getAssertion().getValidFromDate()).isEqualTo(startDate); diff --git a/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java index 4c892802a10..1a7043a10f3 100644 --- a/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java @@ -19,8 +19,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.runner.RunWith; import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; import org.springframework.util.ObjectUtils; +import java.util.Collections; + /** * @author Jitenra Singh * @since 4.2 @@ -37,4 +41,12 @@ protected ObjectMapper buildObjectMapper() { } return mapper; } + + User createDefaultUser() { + return createUser("dummy", "password", "ROLE_USER"); + } + + User createUser(String username, String password, String authority) { + return new User(username, password, Collections.singletonList(new SimpleGrantedAuthority(authority))); + } } diff --git a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java index 5575a98ca3b..542148e8f8f 100644 --- a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java @@ -37,6 +37,14 @@ */ public class AnonymousAuthenticationTokenMixinTests extends AbstractMixinTests { + String hashKey = "key"; + String anonymousAuthTokenJson = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"dummy\", \"password\": %s," + + " \"accountNonExpired\": true, \"enabled\": true, " + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + + "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"authenticated\": true, \"keyHash\": " + hashKey.hashCode() + "," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + @Test(expected = IllegalArgumentException.class) public void testWithNullAuthorities() throws JsonProcessingException, JSONException { new AnonymousAuthenticationToken("key", "principal", null); @@ -49,53 +57,39 @@ public void testWithEmptyAuthorities() throws JsonProcessingException, JSONExcep @Test public void serializeAnonymousAuthenticationTokenTest() throws JsonProcessingException, JSONException { - String key = "key"; - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+ - "\"principal\": \"user\", \"authenticated\": true, \"keyHash\": "+key.hashCode()+","+ - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + User user = createDefaultUser(); AnonymousAuthenticationToken token = new AnonymousAuthenticationToken( - key, "user", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")) + hashKey, user, user.getAuthorities() ); String actualJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, actualJson, true); + JSONAssert.assertEquals(String.format(anonymousAuthTokenJson, "\"password\""), actualJson, true); } @Test public void deserializeAnonymousAuthenticationTokenTest() throws IOException { - String key = "123456789"; - String jsonString = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+ - "\"principal\": \"user\", \"authenticated\": true, \"keyHash\": "+key.hashCode()+","+ - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - AnonymousAuthenticationToken token = buildObjectMapper().readValue(jsonString, AnonymousAuthenticationToken.class); + AnonymousAuthenticationToken token = buildObjectMapper() + .readValue(String.format(anonymousAuthTokenJson,"\"password\""), AnonymousAuthenticationToken.class); assertThat(token).isNotNull(); - assertThat(token.getKeyHash()).isEqualTo(key.hashCode()); + assertThat(token.getKeyHash()).isEqualTo(hashKey.hashCode()); assertThat(token.getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); } @Test(expected = JsonMappingException.class) public void deserializeAnonymousAuthenticationTokenWithoutAuthoritiesTest() throws IOException { - String key = "123456789"; - String jsonString = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+ - "\"principal\": \"user\", \"authenticated\": true, \"keyHash\": "+key.hashCode()+","+ + String jsonString = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null," + + "\"principal\": \"user\", \"authenticated\": true, \"keyHash\": " + hashKey.hashCode() + "," + "\"authorities\": [\"java.util.ArrayList\", []]}"; buildObjectMapper().readValue(jsonString, AnonymousAuthenticationToken.class); } @Test public void serializeAnonymousAuthenticationTokenMixinAfterEraseCredentialTest() throws JsonProcessingException, JSONException { - String key = "key"; - GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); - User user = new User("user", "password", Collections.singleton(authority)); - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null,"+ - "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": null, \"accountNonExpired\": true, \"enabled\": true, " + - "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + - "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"authenticated\": true, \"keyHash\": "+key.hashCode()+","+ - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + User user = createDefaultUser(); AnonymousAuthenticationToken token = new AnonymousAuthenticationToken( - key, user, Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")) + hashKey, user, user.getAuthorities() ); token.eraseCredentials(); String actualJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, actualJson, true); + JSONAssert.assertEquals(String.format(anonymousAuthTokenJson, "null"), actualJson, true); } } diff --git a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java index 9ecd3f1cec5..b55d8f96648 100644 --- a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java @@ -27,7 +27,6 @@ import java.io.IOException; import java.util.Collections; -import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -37,6 +36,18 @@ */ public class RememberMeAuthenticationTokenMixinTests extends AbstractMixinTests { + String rememberMeKey = "rememberMe"; + String rememberMeAuthTokenJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + + "\"keyHash\": " + rememberMeKey.hashCode() + ", \"authenticated\": true, \"details\": null," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"dummy\", \"password\": %s," + + " \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, " + + "\"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + + String rememberMeAuthTokenWithoutUserJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + + "\"keyHash\": " + rememberMeKey.hashCode() + ", \"authenticated\": true, \"details\": null," + + "\"principal\": \"dummy\", \"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + @Test(expected = IllegalArgumentException.class) public void testWithNullPrincipal() throws JsonProcessingException, JSONException { new RememberMeAuthenticationToken("key", null, Collections.emptyList()); @@ -49,66 +60,46 @@ public void testWithNullKey() throws JsonProcessingException, JSONException { @Test public void serializeRememberMeAuthenticationToken() throws JsonProcessingException, JSONException { - String key = "rememberMe"; - RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(key, "user", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + - "\"keyHash\": "+key.hashCode()+", \"principal\": \"user\", \"authenticated\": true, \"details\": null," + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(rememberMeKey, "dummy", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); String actualJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, actualJson, true); + JSONAssert.assertEquals(rememberMeAuthTokenWithoutUserJson, actualJson, true); } @Test public void serializeRememberMeAuthenticationWithUserToken() throws JsonProcessingException, JSONException { - String key = "rememberMe"; - List authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); - RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(key, new User("user", "password", authorities), authorities); - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + - "\"keyHash\": "+key.hashCode()+", \"authenticated\": true, \"details\": null," + - "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"password\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]},"+ - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + User user = createDefaultUser(); + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(rememberMeKey, user, user.getAuthorities()); String actualJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, actualJson, true); + JSONAssert.assertEquals(String.format(rememberMeAuthTokenJson, "\"password\""), actualJson, true); } @Test public void serializeRememberMeAuthenticationWithUserTokenAfterEraseCredential() throws JsonProcessingException, JSONException { - String key = "rememberMe"; - List authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + - "\"keyHash\": "+key.hashCode()+", \"authenticated\": true, \"details\": null," + - "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": null, \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]},"+ - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(key, new User("user", "password", authorities), authorities); + User user = createDefaultUser(); + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(rememberMeKey, user, user.getAuthorities()); token.eraseCredentials(); String actualJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, actualJson, true); + JSONAssert.assertEquals(String.format(rememberMeAuthTokenJson, "null"), actualJson, true); } @Test public void deserializeRememberMeAuthenticationToken() throws IOException { - String key = "rememberMe"; - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + - "\"keyHash\": "+key.hashCode()+", \"principal\": \"user\", \"authenticated\": true, \"details\": null," + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - RememberMeAuthenticationToken token = buildObjectMapper().readValue(expectedJson, RememberMeAuthenticationToken.class); + RememberMeAuthenticationToken token = buildObjectMapper().readValue(rememberMeAuthTokenWithoutUserJson, RememberMeAuthenticationToken.class); assertThat(token).isNotNull(); - assertThat(token.getPrincipal()).isNotNull().isEqualTo("user").isEqualTo(token.getName()); + assertThat(token.getPrincipal()).isNotNull().isEqualTo("dummy").isEqualTo(token.getName()); assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); } @Test public void deserializeRememberMeAuthenticationTokenWithUserTest() throws IOException { - String key = "rememberMe"; - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.RememberMeAuthenticationToken\"," + - "\"keyHash\": "+key.hashCode()+", \"authenticated\": true, \"details\": null," + - "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"password\", \"enabled\": true, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]},"+ - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - RememberMeAuthenticationToken token = buildObjectMapper().readValue(expectedJson, RememberMeAuthenticationToken.class); + RememberMeAuthenticationToken token = buildObjectMapper() + .readValue(String.format(rememberMeAuthTokenJson, "\"password\""), RememberMeAuthenticationToken.class); assertThat(token).isNotNull(); assertThat(token.getPrincipal()).isNotNull().isInstanceOf(User.class); - assertThat(((User)token.getPrincipal()).getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + assertThat(((User)token.getPrincipal()).getUsername()).isEqualTo("dummy"); + assertThat(((User)token.getPrincipal()).getPassword()).isEqualTo("password"); + assertThat(((User) token.getPrincipal()).getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); - assertThat(((User)token.getPrincipal()).isEnabled()).isEqualTo(true); + assertThat(((User) token.getPrincipal()).isEnabled()).isEqualTo(true); } } diff --git a/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTests.java index 5300d33c53c..4a3c16b161f 100644 --- a/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTests.java @@ -36,32 +36,27 @@ */ public class SecurityContextMixinTests extends AbstractMixinTests { + String securityContextJson = "{\"@class\": \"org.springframework.security.core.context.SecurityContextImpl\", \"authentication\": " + + "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + "\"principal\": \"dummy\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]" + + "}" + + "}"; + @Test public void securityContextSerializeTest() throws JsonProcessingException, JSONException { - String expectedJson = "{\"@class\": \"org.springframework.security.core.context.SecurityContextImpl\", \"authentication\": " + - "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - "\"principal\": \"user\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null," + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]" + - "}" + - "}"; SecurityContext context = new SecurityContextImpl(); - context.setAuthentication(new UsernamePasswordAuthenticationToken("user", "password", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")))); + context.setAuthentication(new UsernamePasswordAuthenticationToken("dummy", "password", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")))); String actualJson = buildObjectMapper().writeValueAsString(context); - JSONAssert.assertEquals(expectedJson, actualJson, true); + JSONAssert.assertEquals(securityContextJson, actualJson, true); } @Test public void securityContextDeserializeTest() throws IOException { - String contextJson = "{\"@class\": \"org.springframework.security.core.context.SecurityContextImpl\", \"authentication\": " + - "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - "\"principal\": \"user\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null," + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]" + - "}" + - "}"; - SecurityContext context = buildObjectMapper().readValue(contextJson, SecurityContextImpl.class); + SecurityContext context = buildObjectMapper().readValue(securityContextJson, SecurityContextImpl.class); assertThat(context).isNotNull(); assertThat(context.getAuthentication()).isNotNull().isInstanceOf(UsernamePasswordAuthenticationToken.class); - assertThat(context.getAuthentication().getPrincipal()).isEqualTo("user"); + assertThat(context.getAuthentication().getPrincipal()).isEqualTo("dummy"); assertThat(context.getAuthentication().getCredentials()).isEqualTo("password"); assertThat(context.getAuthentication().isAuthenticated()).isEqualTo(true); assertThat(context.getAuthentication().getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); diff --git a/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTests.java index 9971e9d632a..ed2563f48d6 100644 --- a/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTests.java @@ -37,18 +37,18 @@ */ public class SimpleGrantedAuthorityMixinTests extends AbstractMixinTests { + String simpleGrantedAuthorityJson = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}"; + @Test public void serializeSimpleGrantedAuthorityTest() throws JsonProcessingException, JSONException { SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); String serializeJson = buildObjectMapper().writeValueAsString(authority); - String expectedJson = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}"; - JSONAssert.assertEquals(expectedJson, serializeJson, true); + JSONAssert.assertEquals(simpleGrantedAuthorityJson, serializeJson, true); } @Test public void deserializeGrantedAuthorityTest() throws IOException { - String json = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}"; - SimpleGrantedAuthority authority = buildObjectMapper().readValue(json, SimpleGrantedAuthority.class); + SimpleGrantedAuthority authority = buildObjectMapper().readValue(simpleGrantedAuthorityJson, SimpleGrantedAuthority.class); assertThat(authority).isNotNull(); assertThat(authority.getAuthority()).isNotNull().isEqualTo("ROLE_USER"); } diff --git a/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java b/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java index 697f500b5dd..295a563baae 100644 --- a/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java @@ -36,13 +36,20 @@ */ public class UserDeserializerTests extends AbstractMixinTests { + String userWithAuthoritiesJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"admin\"," + + " \"password\": %s, \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, " + + "\"enabled\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + + String userWithoutAuthoritiesJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"admin\"," + + " \"password\": \"1234\", \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true," + + " \"enabled\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", []]}"; + @Test public void serializeUserTest() throws JsonProcessingException, JSONException { ObjectMapper mapper = buildObjectMapper(); - User user = new User("admin", "1234", Collections.singletonList(new SimpleGrantedAuthority("USER_ROLE"))); + User user = new User("admin", "1234", Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"))); String userJson = mapper.writeValueAsString(user); - String expectedJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"admin\", \"password\": \"1234\", \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"USER_ROLE\"}]]}"; - JSONAssert.assertEquals(expectedJson, userJson, true); + JSONAssert.assertEquals(String.format(userWithAuthoritiesJson, "\"1234\""), userJson, true); } @Test @@ -50,8 +57,7 @@ public void serializeUserWithoutAuthority() throws JsonProcessingException, JSON ObjectMapper mapper = buildObjectMapper(); User user = new User("admin", "1234", Collections.emptyList()); String userJson = mapper.writeValueAsString(user); - String expectedJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"admin\", \"password\": \"1234\", \"accountNonExpired\": true, \"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\", []]}"; - JSONAssert.assertEquals(expectedJson, userJson, true); + JSONAssert.assertEquals(userWithoutAuthoritiesJson, userJson, true); } @Test(expected = IllegalArgumentException.class) @@ -67,13 +73,13 @@ public void deserializeUserWithNullPasswordEmptyAuthorityTest() throws IOExcepti @Test public void deserializeUserWithNullPasswordNoAuthorityTest() throws IOException { String userJsonWithoutPasswordString = "{\"@class\": \"org.springframework.security.core.userdetails.User\", " + - "\"username\": \"user\", \"accountNonExpired\": true, " + + "\"username\": \"admin\", \"accountNonExpired\": true, " + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, " + "\"authorities\": [\"java.util.HashSet\", []]}"; ObjectMapper mapper = buildObjectMapper(); User user = mapper.readValue(userJsonWithoutPasswordString, User.class); assertThat(user).isNotNull(); - assertThat(user.getUsername()).isEqualTo("user"); + assertThat(user.getUsername()).isEqualTo("admin"); assertThat(user.getPassword()).isEqualTo(""); assertThat(user.getAuthorities()).hasSize(0); assertThat(user.isEnabled()).isEqualTo(true); @@ -90,13 +96,10 @@ public void deserializeUserWithNoClassIdInAuthoritiesTest() throws IOException { @Test public void deserializeUserWithClassIdInAuthoritiesTest() throws IOException { - String userJson = "{\"@class\": \"org.springframework.security.core.userdetails.User\", " + - "\"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": true, " + - "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"enabled\": true, " + - "\"authorities\": [\"java.util.Collections$UnmodifiableSet\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - User user = buildObjectMapper().readValue(userJson, User.class); + User user = buildObjectMapper().readValue(String.format(userWithAuthoritiesJson, "\"1234\""), User.class); assertThat(user).isNotNull(); - assertThat(user.getUsername()).isEqualTo("user"); + assertThat(user.getUsername()).isEqualTo("admin"); + assertThat(user.getPassword()).isEqualTo("1234"); assertThat(user.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); } } diff --git a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java index 47ecc78937c..b5bdd58f07f 100644 --- a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java @@ -37,32 +37,39 @@ */ public class UsernamePasswordAuthenticationTokenMixinTests extends AbstractMixinTests { + String unauthenticatedTokenWithoutUserPrincipal = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + " \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": false, \"details\": null, " + + "\"authorities\": [\"java.util.ArrayList\", []]}"; + + String authenticatedTokenWithoutUserPrincipal = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + " \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, " + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + + String authenticatedTokenWithUserPrincipal = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + + "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": %s, \"accountNonExpired\": true, \"enabled\": true, " + + "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + + "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"credentials\": %s," + + "\"details\": null, \"authenticated\": true," + + "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + @Test public void serializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws JsonProcessingException, JSONException { - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - " \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": false, \"details\": null, " + - "\"authorities\": [\"java.util.ArrayList\", []]}"; UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user1", "password"); String serializedJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, serializedJson, true); + JSONAssert.assertEquals(unauthenticatedTokenWithoutUserPrincipal, serializedJson, true); } @Test public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws JsonProcessingException, JSONException { - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - " \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, " + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user1", "password", Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"))); String serializedJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, serializedJson, true); + JSONAssert.assertEquals(authenticatedTokenWithoutUserPrincipal, serializedJson, true); } @Test public void deserializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws IOException, JSONException { - String tokenJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - " \"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": false, \"details\": null, " + - "\"authorities\": [\"java.util.ArrayList\", []], \"name\": \"user1\"}"; - UsernamePasswordAuthenticationToken token = buildObjectMapper().readValue(tokenJson, UsernamePasswordAuthenticationToken.class); + UsernamePasswordAuthenticationToken token = buildObjectMapper() + .readValue(unauthenticatedTokenWithoutUserPrincipal, UsernamePasswordAuthenticationToken.class); assertThat(token).isNotNull(); assertThat(token.isAuthenticated()).isEqualTo(false); assertThat(token.getAuthorities()).isNotNull().hasSize(0); @@ -70,10 +77,8 @@ public void deserializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTe @Test public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws IOException { - String tokenJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - "\"principal\": \"user1\", \"credentials\": \"password\", \"authenticated\": true, \"details\": null, " + - "\"authorities\" : [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; - UsernamePasswordAuthenticationToken token = buildObjectMapper().readValue(tokenJson, UsernamePasswordAuthenticationToken.class); + UsernamePasswordAuthenticationToken token = buildObjectMapper() + .readValue(authenticatedTokenWithoutUserPrincipal, UsernamePasswordAuthenticationToken.class); assertThat(token).isNotNull(); assertThat(token.isAuthenticated()).isEqualTo(true); assertThat(token.getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); @@ -82,28 +87,17 @@ public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenMixinTest @Test public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinWithUserTest() throws JsonProcessingException, JSONException { GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); - User user = new User("user", "pass", Collections.singleton(authority)); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, "pass", Collections.singleton(authority)); - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": true, \"enabled\": true, " + - "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + - "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"credentials\": \"pass\"," + - "\"details\": null, \"authenticated\": true," + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; + User user = new User("user", "password", Collections.singleton(authority)); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, "password", Collections.singleton(authority)); String actualJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, actualJson, true); + JSONAssert.assertEquals(String.format(authenticatedTokenWithUserPrincipal, "password", "password"), actualJson, true); } @Test public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenWithUserTest() throws IOException { - String tokenJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": \"pass\", \"accountNonExpired\": true, \"enabled\": true, " + - "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + - "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"credentials\": \"pass\"," + - "\"details\": null, \"name\": \"user\", \"authenticated\": true," + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; ObjectMapper mapper = buildObjectMapper(); - UsernamePasswordAuthenticationToken token = mapper.readValue(tokenJson, UsernamePasswordAuthenticationToken.class); + UsernamePasswordAuthenticationToken token = mapper + .readValue(String.format(authenticatedTokenWithUserPrincipal, "\"password\"", "\"password\""), UsernamePasswordAuthenticationToken.class); assertThat(token).isNotNull(); assertThat(token.getPrincipal()).isNotNull().isInstanceOf(User.class); assertThat(((User)token.getPrincipal()).getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); @@ -116,14 +110,8 @@ public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinAfterE GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); User user = new User("user", "password", Collections.singleton(authority)); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, "password", Collections.singleton(authority)); - String expectedJson = "{\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," + - "\"principal\": {\"@class\": \"org.springframework.security.core.userdetails.User\", \"username\": \"user\", \"password\": null, \"accountNonExpired\": true, \"enabled\": true, " + - "\"accountNonLocked\": true, \"credentialsNonExpired\": true, \"authorities\": [\"java.util.Collections$UnmodifiableSet\"," + - "[{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}, \"credentials\": null," + - "\"details\": null, \"authenticated\": true," + - "\"authorities\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"role\": \"ROLE_USER\"}]]}"; token.eraseCredentials(); String actualJson = buildObjectMapper().writeValueAsString(token); - JSONAssert.assertEquals(expectedJson, actualJson, true); + JSONAssert.assertEquals(String.format(authenticatedTokenWithUserPrincipal, "null", "null"), actualJson, true); } } diff --git a/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTests.java index 5454a94293c..ff79b90a8aa 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTests.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTests.java @@ -34,6 +34,9 @@ */ public class CookieMixinTests { + String cookieJson = "{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"demo\", \"value\": \"cookie1\"," + + "\"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\": false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}"; + ObjectMapper buildObjectMapper() { ObjectMapper mapper = new ObjectMapper(); SecurityJacksonModules.registerModules(mapper); @@ -43,17 +46,13 @@ ObjectMapper buildObjectMapper() { @Test public void serializeCookie() throws JsonProcessingException, JSONException { Cookie cookie = new Cookie("demo", "cookie1"); - String expectedString = "{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"demo\", \"value\": \"cookie1\"," + - "\"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\": false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}"; String actualString = buildObjectMapper().writeValueAsString(cookie); - JSONAssert.assertEquals(expectedString, actualString, true); + JSONAssert.assertEquals(cookieJson, actualString, true); } @Test public void deserializeCookie() throws IOException { - String cookieString = "{\"@class\": \"javax.servlet.http.Cookie\", \"name\": \"demo\", \"value\": \"cookie1\"," + - "\"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\": false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}"; - Cookie cookie = buildObjectMapper().readValue(cookieString, Cookie.class); + Cookie cookie = buildObjectMapper().readValue(cookieJson, Cookie.class); assertThat(cookie).isNotNull(); assertThat(cookie.getName()).isEqualTo("demo"); assertThat(cookie.getDomain()).isEqualTo(""); diff --git a/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTests.java index 889f51a1018..724750f8d2b 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTests.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixinTests.java @@ -16,7 +16,6 @@ package org.springframework.security.web.jackson2; -import com.fasterxml.jackson.core.JsonProcessingException; import org.json.JSONException; import org.junit.Test; import org.junit.runner.RunWith; @@ -41,6 +40,13 @@ @RunWith(MockitoJUnitRunner.class) public class DefaultSavedRequestMixinTests extends AbstractMixinTests { + String defaultSavedRequestJson = "{" + + "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.web.savedrequest.SavedCookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"domain\": null}]]," + + "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + + "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + + "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ + "}"; + @Test public void matchRequestBuildWithConstructorAndBuilder() { DefaultSavedRequest request = new DefaultSavedRequest.Builder() @@ -56,39 +62,13 @@ public void matchRequestBuildWithConstructorAndBuilder() { assert request.doesRequestMatch(mockRequest, new PortResolverImpl()); } - @Test - public void expectedSerializeTest() throws JsonProcessingException, JSONException { - MockHttpServletRequest request = new MockHttpServletRequest("POST", "/login"); - request.setServerPort(8080); - request.setContextPath("/app"); - request.setCookies(new Cookie("SESSION", "123456789")); - request.addHeader("x-auth-token", "12"); - - DefaultSavedRequest savedRequest = new DefaultSavedRequest(request, new PortResolverImpl()); - - String actualString = buildObjectMapper().writeValueAsString(savedRequest); - String expectedJson = "{\"@class\":\"org.springframework.security.web.savedrequest.DefaultSavedRequest\",\"contextPath\": \"/app\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.web.savedrequest.SavedCookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"secure\": false, \"version\": 0, \"maxAge\": -1, \"comment\": null, \"domain\": null, \"path\": null}]],\n" + - "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"method\": \"POST\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"/login\", \"requestURL\": \"http://localhost:8080/login\",\n" + - "\"scheme\": \"http\", \"serverName\": \"localhost\", \"serverPort\": 8080, \"servletPath\": \"\", \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + - "\"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}}"; - JSONAssert.assertEquals(expectedJson, actualString, true); - } - - @Test public void serializeDefaultRequestBuildWithConstructorTest() throws IOException, JSONException { MockHttpServletRequest request = new MockHttpServletRequest(); request.setCookies(new Cookie("SESSION", "123456789")); request.addHeader("x-auth-token", "12"); - - String expectedJsonString = "{" + - "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.web.savedrequest.SavedCookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"domain\": null}]]," + - "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + - "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + - "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ - "}"; String actualString = buildObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(new DefaultSavedRequest(request, new PortResolverImpl())); - JSONAssert.assertEquals(expectedJsonString, actualString, true); + JSONAssert.assertEquals(defaultSavedRequestJson, actualString, true); } @Test @@ -99,26 +79,13 @@ public void serializeDefaultRequestBuildWithBuilderTest() throws IOException, JS .setScheme("http").setRequestURL("http://localhost").setServerName("localhost").setRequestURI("") .setLocales(Collections.singletonList(new Locale("en"))).setContextPath("").setMethod("") .setServletPath("").build(); - - String expectedJsonString = "{" + - "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.web.savedrequest.SavedCookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"domain\": null}]]," + - "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + - "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + - "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80"+ - "}"; String actualString = buildObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(request); - JSONAssert.assertEquals(expectedJsonString, actualString, true); + JSONAssert.assertEquals(defaultSavedRequestJson, actualString, true); } @Test public void deserializeDefaultSavedRequest() throws IOException { - String jsonString = "{" + - "\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", \"cookies\": [\"java.util.ArrayList\", [{\"@class\": \"org.springframework.security.web.savedrequest.SavedCookie\", \"name\": \"SESSION\", \"value\": \"123456789\", \"comment\": null, \"maxAge\": -1, \"path\": null, \"secure\":false, \"version\": 0, \"isHttpOnly\": false, \"domain\": null}]]," + - "\"locales\": [\"java.util.ArrayList\", [\"en\"]], \"headers\": {\"@class\": \"java.util.TreeMap\", \"x-auth-token\": [\"java.util.ArrayList\", [\"12\"]]}, \"parameters\": {\"@class\": \"java.util.TreeMap\"}," + - "\"contextPath\": \"\", \"method\": \"\", \"pathInfo\": null, \"queryString\": null, \"requestURI\": \"\", \"requestURL\": \"http://localhost\", \"scheme\": \"http\", " + - "\"serverName\": \"localhost\", \"servletPath\": \"\", \"serverPort\": 80" + - "}"; - DefaultSavedRequest request = (DefaultSavedRequest) buildObjectMapper().readValue(jsonString, Object.class); + DefaultSavedRequest request = (DefaultSavedRequest) buildObjectMapper().readValue(defaultSavedRequestJson, Object.class); assertThat(request).isNotNull(); assertThat(request.getCookies()).hasSize(1); assertThat(request.getLocales()).hasSize(1).contains(new Locale("en")); diff --git a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java index 0b18812f64f..e2499b7d73b 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java @@ -42,6 +42,8 @@ public class WebAuthenticationDetailsMixinTests { ObjectMapper mapper; + String webAuthenticationDetailsJson = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," + + "\"sessionId\": \"1\", \"remoteAddress\": \"/localhost\"}"; @Before public void setup() { @@ -57,9 +59,8 @@ public void buildWebAuthenticationDetailsUsingDifferentConstructors() request.setSession(new MockHttpSession(null, "1")); WebAuthenticationDetails details = new WebAuthenticationDetails(request); - String jsonString = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," - + "\"sessionId\": \"1\", \"remoteAddress\": \"/localhost\"}"; - WebAuthenticationDetails authenticationDetails = this.mapper.readValue(jsonString, + + WebAuthenticationDetails authenticationDetails = this.mapper.readValue(webAuthenticationDetailsJson, WebAuthenticationDetails.class); assertThat(details.equals(authenticationDetails)); } @@ -71,18 +72,14 @@ public void webAuthenticationDetailsSerializeTest() request.setRemoteAddr("/home"); request.setSession(new MockHttpSession(null, "1")); WebAuthenticationDetails details = new WebAuthenticationDetails(request); - String expectedJson = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," - + "\"sessionId\": \"1\", \"remoteAddress\": \"/home\"}"; String actualJson = this.mapper.writeValueAsString(details); - JSONAssert.assertEquals(expectedJson, actualJson, true); + JSONAssert.assertEquals(webAuthenticationDetailsJson, actualJson, true); } @Test public void webAuthenticationDetailsDeserializeTest() throws IOException, JSONException { - String actualJson = "{\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\"," - + "\"sessionId\": \"1\", \"remoteAddress\": \"/home\"}"; - WebAuthenticationDetails details = this.mapper.readValue(actualJson, + WebAuthenticationDetails details = this.mapper.readValue(webAuthenticationDetailsJson, WebAuthenticationDetails.class); assertThat(details).isNotNull(); assertThat(details.getRemoteAddress()).isEqualTo("/home"); From c2c152bb5307f5e1992a1fcea235cb7c18bfa352 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Tue, 26 Jul 2016 12:44:24 +0530 Subject: [PATCH 56/62] JavaDocs updated --- .../CasAuthenticationToken.java | 12 +++--- .../cas/jackson2/AssertionImplMixin.java | 6 ++- .../jackson2/AttributePrincipalImplMixin.java | 4 +- .../jackson2/CasAuthenticationTokenMixin.java | 6 +-- .../cas/jackson2/CasJackson2Module.java | 8 +++- .../AbstractAuthenticationToken.java | 2 +- .../AnonymousAuthenticationToken.java | 2 +- .../RememberMeAuthenticationToken.java | 4 +- .../AnonymousAuthenticationTokenMixin.java | 5 ++- .../security/jackson2/CoreJackson2Module.java | 7 +++- .../RememberMeAuthenticationTokenMixin.java | 7 ++-- .../jackson2/SecurityJacksonModules.java | 37 ++++++++++++++++++- .../jackson2/SimpleGrantedAuthorityMixin.java | 8 ++-- .../jackson2/UnmodifiableSetMixin.java | 4 +- .../security/jackson2/UserMixin.java | 5 ++- ...rnamePasswordAuthenticationTokenMixin.java | 7 ++-- .../security/web/jackson2/CookieMixin.java | 4 +- .../web/jackson2/DefaultCsrfTokenMixin.java | 11 ++++-- .../jackson2/DefaultSavedRequestMixin.java | 11 +++--- .../web/jackson2/SavedCookieMixin.java | 27 ++++++++++++++ .../WebAuthenticationDetailsMixin.java | 4 +- .../web/jackson2/WebJackson2Module.java | 8 +++- .../web/savedrequest/DefaultSavedRequest.java | 28 ++------------ .../web/jackson2/SavedCookieMixinTests.java | 16 ++++++++ .../WebAuthenticationDetailsMixinTests.java | 4 +- 25 files changed, 163 insertions(+), 74 deletions(-) diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java index 5e79e7d7863..e8250195f89 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java @@ -66,9 +66,9 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen * @throws IllegalArgumentException if a null was passed */ public CasAuthenticationToken(final String key, final Object principal, - final Object credentials, - final Collection authorities, - final UserDetails userDetails, final Assertion assertion) { + final Object credentials, + final Collection authorities, + final UserDetails userDetails, final Assertion assertion) { this(extractKeyHash(key), principal, credentials, authorities, userDetails, assertion); } @@ -92,9 +92,9 @@ public CasAuthenticationToken(final String key, final Object principal, * @since 4.2 */ private CasAuthenticationToken(final Integer keyHash, final Object principal, - final Object credentials, - final Collection authorities, - final UserDetails userDetails, final Assertion assertion) { + final Object credentials, + final Collection authorities, + final UserDetails userDetails, final Assertion assertion) { super(authorities); if ((principal == null) diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java index aeb708fe27c..19aef8e1f79 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java @@ -17,6 +17,7 @@ package org.springframework.security.cas.jackson2; import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.ObjectMapper; import org.jasig.cas.client.authentication.AttributePrincipal; import java.util.Date; @@ -30,10 +31,13 @@ *

*

  *     ObjectMapper mapper = new ObjectMapper();
- *     mapper.addMixIn(AssertionImpl.class, AssertionImplMixin.class);
+ *     mapper.registerModule(new CasJackson2Module());
  * 
* + * * @author Jitendra Singh + * @see CasJackson2Module + * @see org.springframework.security.jackson2.SecurityJacksonModules * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java index 5112909e8c4..f9e71b2a547 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java @@ -28,10 +28,12 @@ *

*

  *     ObjectMapper mapper = new ObjectMapper();
- *     mapper.addMixIn(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class);
+ *     mapper.registerModule(new CasJackson2Module());
  * 
* * @author Jitendra Singh + * @see CasJackson2Module + * @see org.springframework.security.jackson2.SecurityJacksonModules * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java index 7aa1013460e..7e7ae7847ae 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java @@ -37,12 +37,12 @@ * *
  *     ObjectMapper mapper = new ObjectMapper();
- *     mapper.addMixIn(AssertionImpl.class, AssertionImplMixin.class);
- *     mapper.addMixIn(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class);
- *     mapper.addMixIn(CasAuthenticationToken.class, CasAuthenticationTokenMixin.class);
+ *     mapper.registerModule(new CasJackson2Module());
  * 
* * @author Jitendra Singh + * @see CasJackson2Module + * @see org.springframework.security.jackson2.SecurityJacksonModules * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java b/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java index 59e0963da93..58a0dc7a4dd 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java @@ -17,10 +17,12 @@ package org.springframework.security.cas.jackson2; import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import org.jasig.cas.client.authentication.AttributePrincipalImpl; import org.jasig.cas.client.validation.AssertionImpl; import org.springframework.security.cas.authentication.CasAuthenticationToken; +import org.springframework.security.jackson2.SecurityJacksonModules; /** * Jackson module for spring-security-cas. This module register {@link AssertionImplMixin}, @@ -29,10 +31,13 @@ * *
  *     ObjectMapper mapper = new ObjectMapper();
- *     mapper.registerModule(new CasJackson2SimpleModule());
+ *     mapper.registerModule(new CasJackson2Module());
  * 
+ * Note: use {@link org.springframework.security.jackson2.SecurityJacksonModules#registerModules(ObjectMapper)} + * it'll register all security modules along with basic configuration * * @author Jitendra Singh. + * @see org.springframework.security.jackson2.SecurityJacksonModules * @since 4.2 */ public class CasJackson2Module extends SimpleModule { @@ -43,6 +48,7 @@ public CasJackson2Module() { @Override public void setupModule(SetupContext context) { + SecurityJacksonModules.enableDefaultTyping((ObjectMapper) context.getOwner()); context.setMixInAnnotations(AssertionImpl.class, AssertionImplMixin.class); context.setMixInAnnotations(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class); context.setMixInAnnotations(CasAuthenticationToken.class, CasAuthenticationTokenMixin.class); diff --git a/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java index 360ce593648..eb5c8e06db7 100644 --- a/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java @@ -29,7 +29,7 @@ /** * Base class for Authentication objects. - *

+ *

* Implementations which use this class should be immutable. * * @author Ben Alex diff --git a/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java index 59d604d6d9a..04c1f156f68 100644 --- a/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java @@ -60,7 +60,7 @@ public AnonymousAuthenticationToken(String key, Object principal, * @since 4.2 */ private AnonymousAuthenticationToken(Integer keyHash, Object principal, - Collection authorities) { + Collection authorities) { super(authorities); if (authorities == null || authorities.isEmpty()) { diff --git a/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java index 4d663f70404..3fd5486cbe2 100644 --- a/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java @@ -23,7 +23,7 @@ /** * Represents a remembered Authentication. - *

+ *

* A remembered Authentication must provide a fully valid * Authentication, including the GrantedAuthoritys that apply. * @@ -52,7 +52,7 @@ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken { * @throws IllegalArgumentException if a null was passed */ public RememberMeAuthenticationToken(String key, Object principal, - Collection authorities) { + Collection authorities) { super(authorities); if ((key == null) || ("".equals(key)) || (principal == null) diff --git a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java index 67296546594..c8207958246 100644 --- a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java @@ -28,13 +28,14 @@ * AnonymousAuthenticationToken contains SimpleGrantedAuthority. *

  *     ObjectMapper mapper = new ObjectMapper();
- *     mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
- *     mapper.addMixIn(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class);
+ *     mapper.registerModule(new CoreJackson2Module());
  * 
* * Note: This class will save full class name into a property called @class * * @author Jitendra Singh + * @see CoreJackson2Module + * @see SecurityJacksonModules * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) diff --git a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java index a9448d6e7e9..661c6d33705 100644 --- a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java +++ b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java @@ -17,6 +17,7 @@ package org.springframework.security.jackson2; import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.authentication.RememberMeAuthenticationToken; @@ -34,10 +35,13 @@ * *
  *     ObjectMapper mapper = new ObjectMapper();
- *     mapper.registerModule(new CoreJackson2SimpleModule());
+ *     mapper.registerModule(new CoreJackson2Module());
  * 
+ * Note: use {@link org.springframework.security.jackson2.SecurityJacksonModules#registerModules(ObjectMapper)} + * it'll register all security modules along with basic configuration * * @author Jitendra Singh. + * @see SecurityJacksonModules * @since 4.2 */ public class CoreJackson2Module extends SimpleModule { @@ -48,6 +52,7 @@ public CoreJackson2Module() { @Override public void setupModule(SetupContext context) { + SecurityJacksonModules.enableDefaultTyping((ObjectMapper) context.getOwner()); context.setMixInAnnotations(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class); context.setMixInAnnotations(RememberMeAuthenticationToken.class, RememberMeAuthenticationTokenMixin.class); context.setMixInAnnotations(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class); diff --git a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java index 87c4efc076b..5ea4230895f 100644 --- a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java @@ -34,15 +34,14 @@ * *
  *     ObjectMapper mapper = new ObjectMapper();
- *     mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
- *     mapper.addMixIn({@link org.springframework.security.core.userdetails.User}.class, UserMixin.class);
- *     mapper.addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class);
- *     mapper.addMixIn(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class);
+ *     mapper.registerModule(new CoreJackson2Module());
  * 
* * Note: This class will save TypeInfo (full class name) into a property called @class * * @author Jitendra Singh + * @see CoreJackson2Module + * @see SecurityJacksonModules * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) diff --git a/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java b/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java index 3f7b0744f4c..4c842143b62 100644 --- a/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java +++ b/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.JsonTypeInfo; @@ -10,8 +26,25 @@ import org.springframework.util.ObjectUtils; /** + * This utility class will find and register SecurityModules and configure ObjectMapper. + * If default typing isn't enabled, then this class will enabled default typing. + * + *
+ *     ObjectMapper mapper = new ObjectMapper();
+ *     SecurityJacksonModules.registerModules(mapper);
+ * 
+ * + * Above code is equivalent to + *
+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+ *     mapper.registerModule(new CoreJackson2Module());
+ *     mapper.registerModule(new CasJackson2Module());
+ *     mapper.registerModule(new WebJackson2Module());
+ * 
+ * * @author Jitendra Singh. - * @Since 4.2 + * @since 4.2 */ public final class SecurityJacksonModules { @@ -20,7 +53,7 @@ public final class SecurityJacksonModules { private SecurityJacksonModules() { } - private static void enableDefaultTyping(ObjectMapper mapper) { + public static void enableDefaultTyping(ObjectMapper mapper) { TypeResolverBuilder typeBuilder = mapper.getDeserializationConfig().getDefaultTyper(null); if (ObjectUtils.isEmpty(typeBuilder)) { mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); diff --git a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java index d08a4895f95..fd11cf14e18 100644 --- a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java @@ -17,10 +17,6 @@ package org.springframework.security.jackson2; import com.fasterxml.jackson.annotation.*; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.springframework.security.core.GrantedAuthority; - -import java.util.Collection; /** * Jackson Mixin class helps in serialize/deserialize @@ -28,9 +24,11 @@ * *
  *     ObjectMapper mapper = new ObjectMapper();
- *     mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
+ *     mapper.registerModule(new CoreJackson2Module());
  * 
* @author Jitendra Singh + * @see CoreJackson2Module + * @see SecurityJacksonModules * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) diff --git a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java index d932af1bb09..3fd3875efde 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java @@ -27,10 +27,12 @@ * *
  *     ObjectMapper mapper = new ObjectMapper();
- *     mapper.addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class);
+ *     mapper.registerModule(new CoreJackson2Module());
  * 
* * @author Jitendra Singh + * @see CoreJackson2Module + * @see SecurityJacksonModules * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) diff --git a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java index 63104c35b5f..3f86ac92a20 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java @@ -31,12 +31,13 @@ * *
  *     ObjectMapper mapper = new ObjectMapper();
- *     mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
- *     mapper.addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class);
+ *     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) diff --git a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java index d19fa7a01bd..9815b687372 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixin.java @@ -33,12 +33,11 @@ * *
  *     ObjectMapper mapper = new ObjectMapper();
- *     mapper.addMixIn(Collections.unmodifiableSet(Collections.EMPTY_SET).getClass(), UnmodifiableSetMixin.class);
- *     mapper.addMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
- *     mapper.addMixIn(User.class, UserMixin.class);
- *     mapper.addMixIn(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class);
+ *     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") diff --git a/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java index 634027ae72b..9b5816a6460 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/CookieMixin.java @@ -25,10 +25,12 @@ * *
  *     ObjectMapper mapper = new ObjectMapper();
- *     mapper.addMixIn(Cookie.class, CookieMixin.class);
+ *     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) diff --git a/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java index ea4d7baf0a1..46be5b66701 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixin.java @@ -16,18 +16,23 @@ package org.springframework.security.web.jackson2; -import com.fasterxml.jackson.annotation.*; +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.addMixIn(DefaultCsrfToken.class, DefaultCsrfTokenMixin.class);
+ * 		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") diff --git a/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java index 3229d2e5a85..404fd1e7cab 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java @@ -26,18 +26,19 @@ import java.util.Map; /** - * ` * Jackson mixin class to serialize/deserialize {@link DefaultSavedRequest}. This mixin use + * Jackson mixin class to serialize/deserialize {@link DefaultSavedRequest}. This mixin use * {@link org.springframework.security.web.savedrequest.DefaultSavedRequest.Builder} to - * deserialized josn.In order to use this mixin class you also need to register + * deserialized json.In order to use this mixin class you also need to register * {@link CookieMixin}. - *

+ *

*

  *     ObjectMapper mapper = new ObjectMapper();
- *     mapper.addMixIn(Cookie.class, CookieMixin.class);
- *     mapper.addMixIn(DefaultSavedRequest.class, DefaultSavedRequestMixin.class);
+ *     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) diff --git a/web/src/main/java/org/springframework/security/web/jackson2/SavedCookieMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/SavedCookieMixin.java index b8db7243c92..a048cb82f2e 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/SavedCookieMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/SavedCookieMixin.java @@ -1,9 +1,36 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.*; /** + * 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, diff --git a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java index 3bd35303f60..c07918aeab7 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixin.java @@ -23,10 +23,12 @@ * *
  * 	ObjectMapper mapper = new ObjectMapper();
- *	mapper.addMixIn(WebAuthenticationDetails.class, WebAuthenticationDetailsMixin.class);
+ *	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) diff --git a/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2Module.java b/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2Module.java index d591993546d..464f86e2060 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2Module.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2Module.java @@ -17,7 +17,9 @@ package org.springframework.security.web.jackson2; 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; @@ -32,10 +34,13 @@ * *
  *     ObjectMapper mapper = new ObjectMapper();
- *     mapper.registerModule(new WebJackson2SimpleModule());
+ *     mapper.registerModule(new WebJackson2Module());
  * 
+ * Note: use {@link org.springframework.security.jackson2.SecurityJacksonModules#registerModules(ObjectMapper)} + * it'll register all security modules along with basic configuration * * @author Jitendra Singh + * @see SecurityJacksonModules * @since 4.2 */ public class WebJackson2Module extends SimpleModule { @@ -46,6 +51,7 @@ public WebJackson2Module() { @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); diff --git a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java index de59c599a58..a3982f795d5 100644 --- a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java +++ b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java @@ -31,18 +31,18 @@ /** * Represents central information from a {@code HttpServletRequest}. - *

+ *

* This class is used by * {@link org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter} * and {@link org.springframework.security.web.savedrequest.SavedRequestAwareWrapper} to * reproduce the request after successful authentication. An instance of this class is * stored at the time of an authentication exception by * {@link org.springframework.security.web.access.ExceptionTranslationFilter}. - *

+ *

* IMPLEMENTATION NOTE: It is assumed that this object is accessed only from the * context of a single thread, so no synchronization around internal collection classes is * performed. - *

+ *

* This class is based on code in Apache Tomcat. * * @author Craig McClanahan @@ -208,7 +208,7 @@ private void addParameter(String name, String[] values) { /** * Determines if the current request matches the DefaultSavedRequest. - *

+ *

* All URL arguments are considered but not cookies, locales, headers or parameters. * * @param request the actual request to be matched against this one @@ -481,26 +481,6 @@ public Builder setServerPort(int serverPort) { return this; } - @Override - public String toString() { - return "Builder{" + - "cookies=" + cookies + - ", locales=" + locales + - ", headers=" + headers + - ", parameters=" + parameters + - ", contextPath='" + contextPath + '\'' + - ", method='" + method + '\'' + - ", pathInfo='" + pathInfo + '\'' + - ", queryString='" + queryString + '\'' + - ", requestURI='" + requestURI + '\'' + - ", requestURL='" + requestURL + '\'' + - ", scheme='" + scheme + '\'' + - ", serverName='" + serverName + '\'' + - ", servletPath='" + servletPath + '\'' + - ", serverPort=" + serverPort + - '}'; - } - public DefaultSavedRequest build() { DefaultSavedRequest savedRequest = new DefaultSavedRequest(this); System.out.println("Building Default Saved request object"); diff --git a/web/src/test/java/org/springframework/security/web/jackson2/SavedCookieMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/SavedCookieMixinTests.java index 8dc8ffd3336..f86c6e92676 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/SavedCookieMixinTests.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/SavedCookieMixinTests.java @@ -1,3 +1,19 @@ +/* + * 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.jackson2; import com.fasterxml.jackson.annotation.JsonAutoDetect; diff --git a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java index e2499b7d73b..9624129035f 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java @@ -69,7 +69,7 @@ public void buildWebAuthenticationDetailsUsingDifferentConstructors() public void webAuthenticationDetailsSerializeTest() throws JsonProcessingException, JSONException { MockHttpServletRequest request = new MockHttpServletRequest(); - request.setRemoteAddr("/home"); + request.setRemoteAddr("/localhost"); request.setSession(new MockHttpSession(null, "1")); WebAuthenticationDetails details = new WebAuthenticationDetails(request); String actualJson = this.mapper.writeValueAsString(details); @@ -82,7 +82,7 @@ public void webAuthenticationDetailsDeserializeTest() WebAuthenticationDetails details = this.mapper.readValue(webAuthenticationDetailsJson, WebAuthenticationDetails.class); assertThat(details).isNotNull(); - assertThat(details.getRemoteAddress()).isEqualTo("/home"); + assertThat(details.getRemoteAddress()).isEqualTo("/localhost"); assertThat(details.getSessionId()).isEqualTo("1"); } } From 97af1c3e2117d32f23500443d024c2df931c6f36 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Bisht Date: Tue, 26 Jul 2016 12:54:13 +0530 Subject: [PATCH 57/62] Unused imports removed --- .../security/cas/jackson2/AssertionImplMixin.java | 1 - .../security/web/jackson2/DefaultSavedRequestMixin.java | 4 ---- 2 files changed, 5 deletions(-) diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java index 19aef8e1f79..0e3dc552bed 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java @@ -17,7 +17,6 @@ package org.springframework.security.cas.jackson2; import com.fasterxml.jackson.annotation.*; -import com.fasterxml.jackson.databind.ObjectMapper; import org.jasig.cas.client.authentication.AttributePrincipal; import java.util.Date; diff --git a/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java b/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java index 404fd1e7cab..b896882e202 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/DefaultSavedRequestMixin.java @@ -17,14 +17,10 @@ package org.springframework.security.web.jackson2; 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.web.savedrequest.DefaultSavedRequest; -import java.util.Map; - /** * Jackson mixin class to serialize/deserialize {@link DefaultSavedRequest}. This mixin use * {@link org.springframework.security.web.savedrequest.DefaultSavedRequest.Builder} to From 3cb4be412a464cdedb7e8d52be5b17dd5c6cc5df Mon Sep 17 00:00:00 2001 From: Jitendra Singh Date: Wed, 3 Aug 2016 19:22:42 +0530 Subject: [PATCH 58/62] addModules() added to get list of security modules --- .../jackson2/SecurityJacksonModules.java | 64 +++++++++++++++++-- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java b/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java index 4c842143b62..4babca65b34 100644 --- a/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java +++ b/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java @@ -22,9 +22,14 @@ import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** * This utility class will find and register SecurityModules and configure ObjectMapper. * If default typing isn't enabled, then this class will enabled default typing. @@ -34,7 +39,15 @@ * SecurityJacksonModules.registerModules(mapper); *

* + * You can also configure ObjectMapper with your own configuration then register security modules + * + *
+ *     ObjectMapper mapper = new ObjectMapper();
+ *     mapper.registerModules(SecurityJacksonModules.getModules());
+ * 
+ * * Above code is equivalent to + * *
  *     ObjectMapper mapper = new ObjectMapper();
  *     mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
@@ -43,12 +56,19 @@
  *     mapper.registerModule(new WebJackson2Module());
  * 
* + * Use method {@link SecurityJacksonModules#getModules()} to list available SecurityJackson2Modules. + * * @author Jitendra Singh. * @since 4.2 */ public final class SecurityJacksonModules { private static final Log logger = LogFactory.getLog(SecurityJacksonModules.class); + private static final List securityJackson2ModuleClasses = Arrays.asList( + "org.springframework.security.jackson2.CoreJackson2Module", + "org.springframework.security.cas.jackson2.CasJackson2Module", + "org.springframework.security.web.jackson2.WebJackson2Module" + ); private SecurityJacksonModules() { } @@ -60,27 +80,59 @@ public static void enableDefaultTyping(ObjectMapper mapper) { } } - private static void findAndRegisterSecurityModuleClass(ObjectMapper mapper, String className) { + private static Module loadAndGetInstance(String className) { + Module instance = null; try { logger.debug("Loading module " + className); Class casModuleClass = (Class) ClassUtils.forName(className, ClassUtils.getDefaultClassLoader()); if (!ObjectUtils.isEmpty(casModuleClass)) { logger.debug("Loaded module " + className + ", now registering"); - mapper.registerModule(casModuleClass.newInstance()); + instance = casModuleClass.newInstance(); } } catch (ClassNotFoundException e) { - logger.warn("Module class not found : "+e.getMessage()); + logger.warn("Module class not found : " + e.getMessage()); } catch (InstantiationException e) { logger.error(e.getMessage()); } catch (IllegalAccessException e) { logger.error(e.getMessage()); } + return instance; + } + + private static void registerSecurityModules(ObjectMapper mapper, List securityModules) { + if (!ObjectUtils.isEmpty(securityModules)) { + mapper.registerModules(securityModules); + } } + /** + * This method will register SecurityJackson2 Modules. + * + * @param mapper + */ public static void registerModules(ObjectMapper mapper) { + Assert.notNull(mapper); + enableDefaultTyping(mapper); - mapper.registerModule(new CoreJackson2Module()); - findAndRegisterSecurityModuleClass(mapper, "org.springframework.security.cas.jackson2.CasJackson2Module"); - findAndRegisterSecurityModuleClass(mapper, "org.springframework.security.web.jackson2.WebJackson2Module"); + List modules = getModules(); + if(!ObjectUtils.isEmpty(modules)) { + registerSecurityModules(mapper, modules); + } + } + + /** + * List of available security modules. + * + * @return + */ + public static List getModules() { + List modules = new ArrayList(); + for(String className : securityJackson2ModuleClasses) { + Module module = loadAndGetInstance(className); + if(!ObjectUtils.isEmpty(module)) { + modules.add(module); + } + } + return modules; } } From 08323a9a42a6baf4d9e2ca32bdaea59049f5398c Mon Sep 17 00:00:00 2001 From: Jitendra Singh Date: Tue, 9 Aug 2016 23:57:14 +0530 Subject: [PATCH 59/62] extra logs removed --- .../security/web/savedrequest/DefaultSavedRequest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java index a3982f795d5..5a5811c77af 100644 --- a/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java +++ b/web/src/main/java/org/springframework/security/web/savedrequest/DefaultSavedRequest.java @@ -483,8 +483,6 @@ public Builder setServerPort(int serverPort) { public DefaultSavedRequest build() { DefaultSavedRequest savedRequest = new DefaultSavedRequest(this); - System.out.println("Building Default Saved request object"); - System.out.println(this.toString()); if(!ObjectUtils.isEmpty(this.cookies)) { for (SavedCookie cookie : this.cookies) { savedRequest.addCookie(cookie.getCookie()); From efffa78526dba646943e594e41dbc218f420cf67 Mon Sep 17 00:00:00 2001 From: Jitendra Singh Date: Tue, 9 Aug 2016 23:57:39 +0530 Subject: [PATCH 60/62] typo fixed in variable name --- .../security/jackson2/SecurityJacksonModules.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java b/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java index 4babca65b34..e970ee21882 100644 --- a/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java +++ b/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java @@ -84,10 +84,10 @@ private static Module loadAndGetInstance(String className) { Module instance = null; try { logger.debug("Loading module " + className); - Class casModuleClass = (Class) ClassUtils.forName(className, ClassUtils.getDefaultClassLoader()); - if (!ObjectUtils.isEmpty(casModuleClass)) { + Class securityModule = (Class) ClassUtils.forName(className, ClassUtils.getDefaultClassLoader()); + if (!ObjectUtils.isEmpty(securityModule)) { logger.debug("Loaded module " + className + ", now registering"); - instance = casModuleClass.newInstance(); + instance = securityModule.newInstance(); } } catch (ClassNotFoundException e) { logger.warn("Module class not found : " + e.getMessage()); From 9e7e2cb0843f1e0f6d165b1525e2e27ce0edaa6c Mon Sep 17 00:00:00 2001 From: Jitendra Singh Date: Tue, 9 Aug 2016 23:58:04 +0530 Subject: [PATCH 61/62] httpOnly field name fixed in CookieDeserializer --- .../security/web/jackson2/CookieDeserializer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java b/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java index 21248853d63..ff6876a61b1 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/CookieDeserializer.java @@ -51,7 +51,7 @@ public Cookie deserialize(JsonParser jp, DeserializationContext ctxt) throws IOE cookie.setSecure(readJsonNode(jsonNode, "secure").asBoolean()); cookie.setVersion(readJsonNode(jsonNode, "version").asInt()); cookie.setPath(readJsonNode(jsonNode, "path").asText()); - cookie.setHttpOnly(readJsonNode(jsonNode, "isHttpOnly").asBoolean()); + cookie.setHttpOnly(readJsonNode(jsonNode, "httpOnly").asBoolean()); return cookie; } From b35f44aaf7f94a73cce7a9a29b7171643a24f4dd Mon Sep 17 00:00:00 2001 From: Jitendra Singh Date: Wed, 10 Aug 2016 02:09:27 +0530 Subject: [PATCH 62/62] registerModules method replaced with getModules --- .../cas/jackson2/CasJackson2Module.java | 6 +-- .../CasAuthenticationTokenMixinTests.java | 2 +- .../security/jackson2/CoreJackson2Module.java | 6 +-- .../jackson2/SecurityJacksonModules.java | 54 ++++--------------- .../security/jackson2/AbstractMixinTests.java | 2 +- .../web/jackson2/WebJackson2Module.java | 6 +-- .../web/jackson2/AbstractMixinTests.java | 2 +- .../web/jackson2/CookieMixinTests.java | 2 +- .../jackson2/DefaultCsrfTokenMixinTests.java | 2 +- .../WebAuthenticationDetailsMixinTests.java | 2 +- 10 files changed, 26 insertions(+), 58 deletions(-) diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java b/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java index 58a0dc7a4dd..8d7bf6046af 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java @@ -26,15 +26,15 @@ /** * Jackson module for spring-security-cas. This module register {@link AssertionImplMixin}, - * {@link AttributePrincipalImplMixin} and {@link CasAuthenticationTokenMixin}. In order to use this module just + * {@link AttributePrincipalImplMixin} and {@link CasAuthenticationTokenMixin}. 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 CasJackson2Module());
  * 
- * Note: use {@link org.springframework.security.jackson2.SecurityJacksonModules#registerModules(ObjectMapper)} - * it'll register all security modules along with basic configuration + * Note: use {@link SecurityJacksonModules#getModules()} to get list of all security modules. * * @author Jitendra Singh. * @see org.springframework.security.jackson2.SecurityJacksonModules diff --git a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java index 87262bd0862..8605a12a230 100644 --- a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java +++ b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java @@ -72,7 +72,7 @@ private CasAuthenticationToken createCasAuthenticationToken() { ObjectMapper buildObjectMapper() { ObjectMapper mapper = new ObjectMapper(); - SecurityJacksonModules.registerModules(mapper); + mapper.registerModules(SecurityJacksonModules.getModules()); return mapper; } diff --git a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java index 661c6d33705..7db25de05f0 100644 --- a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java +++ b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java @@ -30,15 +30,15 @@ /** * Jackson module for spring-security-core. This module register {@link AnonymousAuthenticationTokenMixin}, * {@link RememberMeAuthenticationTokenMixin}, {@link SimpleGrantedAuthorityMixin}, {@link UnmodifiableSetMixin}, - * {@link UserMixin} and {@link UsernamePasswordAuthenticationTokenMixin}. In order to use this module just + * {@link UserMixin} and {@link UsernamePasswordAuthenticationTokenMixin}. 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 CoreJackson2Module());
  * 
- * Note: use {@link org.springframework.security.jackson2.SecurityJacksonModules#registerModules(ObjectMapper)} - * it'll register all security modules along with basic configuration + * Note: use {@link SecurityJacksonModules#getModules()} to get list of all security modules. * * @author Jitendra Singh. * @see SecurityJacksonModules diff --git a/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java b/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java index e970ee21882..27603fe97ac 100644 --- a/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java +++ b/core/src/main/java/org/springframework/security/jackson2/SecurityJacksonModules.java @@ -22,7 +22,6 @@ import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; @@ -31,23 +30,15 @@ import java.util.List; /** - * This utility class will find and register SecurityModules and configure ObjectMapper. - * If default typing isn't enabled, then this class will enabled default typing. + * This utility class will find all the SecurityModules in classpath. * + *

*

  *     ObjectMapper mapper = new ObjectMapper();
- *     SecurityJacksonModules.registerModules(mapper);
- * 
- * - * You can also configure ObjectMapper with your own configuration then register security modules - * - *
- *     ObjectMapper mapper = new ObjectMapper();
  *     mapper.registerModules(SecurityJacksonModules.getModules());
  * 
- * * Above code is equivalent to - * + *

*

  *     ObjectMapper mapper = new ObjectMapper();
  *     mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
@@ -56,8 +47,6 @@
  *     mapper.registerModule(new WebJackson2Module());
  * 
* - * Use method {@link SecurityJacksonModules#getModules()} to list available SecurityJackson2Modules. - * * @author Jitendra Singh. * @since 4.2 */ @@ -74,9 +63,11 @@ private SecurityJacksonModules() { } public static void enableDefaultTyping(ObjectMapper mapper) { - TypeResolverBuilder typeBuilder = mapper.getDeserializationConfig().getDefaultTyper(null); - if (ObjectUtils.isEmpty(typeBuilder)) { - mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); + if(!ObjectUtils.isEmpty(mapper)) { + TypeResolverBuilder typeBuilder = mapper.getDeserializationConfig().getDefaultTyper(null); + if (ObjectUtils.isEmpty(typeBuilder)) { + mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); + } } } @@ -99,37 +90,14 @@ private static Module loadAndGetInstance(String className) { return instance; } - private static void registerSecurityModules(ObjectMapper mapper, List securityModules) { - if (!ObjectUtils.isEmpty(securityModules)) { - mapper.registerModules(securityModules); - } - } - - /** - * This method will register SecurityJackson2 Modules. - * - * @param mapper - */ - public static void registerModules(ObjectMapper mapper) { - Assert.notNull(mapper); - - enableDefaultTyping(mapper); - List modules = getModules(); - if(!ObjectUtils.isEmpty(modules)) { - registerSecurityModules(mapper, modules); - } - } - /** - * List of available security modules. - * - * @return + * @return List of available security modules in classpath. */ public static List getModules() { List modules = new ArrayList(); - for(String className : securityJackson2ModuleClasses) { + for (String className : securityJackson2ModuleClasses) { Module module = loadAndGetInstance(className); - if(!ObjectUtils.isEmpty(module)) { + if (!ObjectUtils.isEmpty(module)) { modules.add(module); } } diff --git a/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java index 1a7043a10f3..8b78118d3e9 100644 --- a/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java @@ -37,7 +37,7 @@ public abstract class AbstractMixinTests { protected ObjectMapper buildObjectMapper() { if (ObjectUtils.isEmpty(mapper)) { mapper = new ObjectMapper(); - SecurityJacksonModules.registerModules(mapper); + mapper.registerModules(SecurityJacksonModules.getModules()); } return mapper; } diff --git a/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2Module.java b/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2Module.java index 464f86e2060..197537e865f 100644 --- a/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2Module.java +++ b/web/src/main/java/org/springframework/security/web/jackson2/WebJackson2Module.java @@ -29,15 +29,15 @@ /** * Jackson module for spring-security-web. This module register {@link CookieMixin}, - * {@link DefaultCsrfTokenMixin}, {@link DefaultSavedRequestMixin} and {@link WebAuthenticationDetailsMixin}. + * {@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 org.springframework.security.jackson2.SecurityJacksonModules#registerModules(ObjectMapper)} - * it'll register all security modules along with basic configuration + * Note: use {@link SecurityJacksonModules#getModules()} to get list of all security modules. * * @author Jitendra Singh * @see SecurityJacksonModules diff --git a/web/src/test/java/org/springframework/security/web/jackson2/AbstractMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/AbstractMixinTests.java index 34114ae1a08..7523385a3c1 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/AbstractMixinTests.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/AbstractMixinTests.java @@ -34,7 +34,7 @@ public abstract class AbstractMixinTests { protected ObjectMapper buildObjectMapper() { if (ObjectUtils.isEmpty(mapper)) { mapper = new ObjectMapper(); - SecurityJacksonModules.registerModules(mapper); + mapper.registerModules(SecurityJacksonModules.getModules()); } return mapper; } diff --git a/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTests.java index ff79b90a8aa..251f26e3f3d 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTests.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/CookieMixinTests.java @@ -39,7 +39,7 @@ public class CookieMixinTests { ObjectMapper buildObjectMapper() { ObjectMapper mapper = new ObjectMapper(); - SecurityJacksonModules.registerModules(mapper); + mapper.registerModules(SecurityJacksonModules.getModules()); return mapper; } diff --git a/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java index f3e0b6e445c..4944173bc52 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/DefaultCsrfTokenMixinTests.java @@ -45,7 +45,7 @@ public class DefaultCsrfTokenMixinTests { @Before public void setup() { objectMapper = new ObjectMapper(); - SecurityJacksonModules.registerModules(objectMapper); + objectMapper.registerModules(SecurityJacksonModules.getModules()); defaultCsrfTokenJson = "{\"@class\": \"org.springframework.security.web.csrf.DefaultCsrfToken\", " + "\"headerName\": \"csrf-header\", \"parameterName\": \"_csrf\", \"token\": \"1\"}"; } diff --git a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java index 9624129035f..9cc8d54b44b 100644 --- a/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java +++ b/web/src/test/java/org/springframework/security/web/jackson2/WebAuthenticationDetailsMixinTests.java @@ -48,7 +48,7 @@ public class WebAuthenticationDetailsMixinTests { @Before public void setup() { this.mapper = new ObjectMapper(); - SecurityJacksonModules.registerModules(mapper); + this.mapper.registerModules(SecurityJacksonModules.getModules()); } @Test