From a2e2e92f5a52482246a7cb30b789fc4945fc7b2c Mon Sep 17 00:00:00 2001 From: Nicholas Blair <nicholas.blair@wisc.edu> Date: Wed, 24 Aug 2016 09:39:19 -0500 Subject: [PATCH] fix: provide factory method for jackson to deserialize authorities @JsonProperty won't work with the abstract '? extends GrantedAuthority' type, as Jackson doesn't have a constructor or factory to convert a string into a concrete implementation. This change adds a factory method which takes a Collection<String> (which Jackson can understand) and uses Spring Security's utility method to convert the Collection of Strings to a Collection of GrantedAuthority instances. Note: the 'Amy Administrator' user provided by the 'local-users.json|yaml' file is no longer strictly equivalent to those provided in 'local-users.properties'. See https://git.doit.wisc.edu/adi-ia/uw-spring-security/issues/5; correcting that seems to be outside of the scope of a bugfix, as it will result in something that likely requires a new feature release. --- .../java/edu/wisc/uwss/UWUserDetailsImpl.java | 38 ++++++++++++++----- .../edu/wisc/uwss/local/local-users.json | 2 +- .../edu/wisc/uwss/local/local-users.yaml | 3 +- .../LocalUserDetailsManagerImplTest.java | 10 +++++ 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/uw-spring-security-core/src/main/java/edu/wisc/uwss/UWUserDetailsImpl.java b/uw-spring-security-core/src/main/java/edu/wisc/uwss/UWUserDetailsImpl.java index dd253b6..2e73b58 100644 --- a/uw-spring-security-core/src/main/java/edu/wisc/uwss/UWUserDetailsImpl.java +++ b/uw-spring-security-core/src/main/java/edu/wisc/uwss/UWUserDetailsImpl.java @@ -9,6 +9,7 @@ import java.util.Collections; import org.apache.commons.lang3.StringUtils; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.User; import org.springframework.util.DigestUtils; @@ -54,6 +55,7 @@ public class UWUserDetailsImpl extends User implements UWUserDetails, HasModifia /** * The primary constructor for {@link UWUserDetails}. + * * @param pvi * @param username * @param password @@ -61,22 +63,40 @@ public class UWUserDetailsImpl extends User implements UWUserDetails, HasModifia * @param emailAddress * @param uddsMembership * @param grantedAuthorities - * - * No other constructors should be annotated with JsonCreator. - * @see http://stackoverflow.com/questions/15931082/how-to-deserialize-a-class-with-overloaded-constructors-using-jsoncreator */ - @JsonCreator - public UWUserDetailsImpl(@JsonProperty("pvi") String pvi, @JsonProperty("username") String username, @JsonProperty("password") String password, - @JsonProperty("fullName") String fullName, @JsonProperty("emailAddress") String emailAddress, - @JsonProperty("uddsMembership") Collection<String> uddsMembership, @JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities) { + public UWUserDetailsImpl(String pvi, String username, String password, + String fullName, String emailAddress, + Collection<String> uddsMembership, Collection<? extends GrantedAuthority> authorities) { super(username, password, authorities); this.pvi = pvi; this.fullName = fullName; this.uddsMembership = uddsMembership; this.emailAddress = StringUtils.isNotBlank(emailAddress) ? - emailAddress.trim().toLowerCase() : emailAddress; + emailAddress.trim().toLowerCase() : emailAddress; this.emailAddressHash = StringUtils.isNotBlank(emailAddress) ? DigestUtils - .md5DigestAsHex(this.emailAddress.getBytes()) : null; + .md5DigestAsHex(this.emailAddress.getBytes()) : null; + } + + /** + * Utility factory method to help Jackson deserialize JSON objects to instances of this class. + * There can be only one constructor or factory method on the class with {@link JsonCreator} + * annotation. + * + * @param pvi + * @param username + * @param password + * @param fullName + * @param emailAddress + * @param uddsMembership + * @param authorities + */ + @JsonCreator + public static UWUserDetailsImpl newInstance(@JsonProperty("pvi") String pvi, @JsonProperty("username") String username, @JsonProperty("password") String password, + @JsonProperty("fullName") String fullName, @JsonProperty("emailAddress") String emailAddress, + @JsonProperty("uddsMembership") Collection<String> uddsMembership, @JsonProperty("authorities") Collection<String> authorities) { + return new UWUserDetailsImpl(pvi, username, password, fullName, emailAddress, + uddsMembership, + AuthorityUtils.createAuthorityList(authorities.toArray(new String[]{}))); } /** diff --git a/uw-spring-security-core/src/main/resources/edu/wisc/uwss/local/local-users.json b/uw-spring-security-core/src/main/resources/edu/wisc/uwss/local/local-users.json index 2b90305..7ad27b0 100644 --- a/uw-spring-security-core/src/main/resources/edu/wisc/uwss/local/local-users.json +++ b/uw-spring-security-core/src/main/resources/edu/wisc/uwss/local/local-users.json @@ -8,7 +8,7 @@ "emailAddress": "amy.administrator@demo.wisc.edu", "pvi": "UW000A000", "uddsMembership": [ "A535900" ], - "authorities": [] + "authorities": [ "edu.wisc.uwss.local.administrator" ] }, { "username": "jane", diff --git a/uw-spring-security-core/src/main/resources/edu/wisc/uwss/local/local-users.yaml b/uw-spring-security-core/src/main/resources/edu/wisc/uwss/local/local-users.yaml index 677bf6f..0ee9082 100644 --- a/uw-spring-security-core/src/main/resources/edu/wisc/uwss/local/local-users.yaml +++ b/uw-spring-security-core/src/main/resources/edu/wisc/uwss/local/local-users.yaml @@ -6,7 +6,8 @@ emailAddress: "amy.administrator@demo.wisc.edu" uddsMembership: - "A535900" - authorities: [] + authorities: + - "edu.wisc.uwss.local.administrator" firstName: "Amy" lastName: "Administrator" - pvi: "UW000A001" diff --git a/uw-spring-security-core/src/test/java/edu/wisc/uwss/local/LocalUserDetailsManagerImplTest.java b/uw-spring-security-core/src/test/java/edu/wisc/uwss/local/LocalUserDetailsManagerImplTest.java index e24c411..4a4c972 100644 --- a/uw-spring-security-core/src/test/java/edu/wisc/uwss/local/LocalUserDetailsManagerImplTest.java +++ b/uw-spring-security-core/src/test/java/edu/wisc/uwss/local/LocalUserDetailsManagerImplTest.java @@ -91,6 +91,11 @@ public class LocalUserDetailsManagerImplTest { * Confirm that {@link LocalUserDetailsManagerImpl} with {@link LocalUserDetailsManagerImpl#setLoaderEnabled(boolean)} * of true results in equivalent {@link UWUserDetails} instances being loaded from JSON. * + * Note: As of 1.5.x, this test passes, but potentially should not, as the {@link UWUserDetails} + * provided by the default {@link LocalUserDetailsAttributesMapper} do not have any + * {@link GrantedAuthority}, where the {@link UWUserDetails} provided by the + * {@link LocalUserDetailsLoader} do. See https://git.doit.wisc.edu/adi-ia/uw-spring-security/issues/5. + * * @throws IOException */ @Test @@ -118,6 +123,11 @@ public class LocalUserDetailsManagerImplTest { * Confirm that {@link LocalUserDetailsManagerImpl} with {@link LocalUserDetailsManagerImpl#setLoaderEnabled(boolean)} * of true results in equivalent {@link UWUserDetails} instances being loaded from YAML. * + * Note: As of 1.5.x, this test passes, but potentially should not, as the {@link UWUserDetails} + * provided by the default {@link LocalUserDetailsAttributesMapper} do not have any + * {@link GrantedAuthority}, where the {@link UWUserDetails} provided by the + * {@link LocalUserDetailsLoader} do. See https://git.doit.wisc.edu/adi-ia/uw-spring-security/issues/5. + * * @throws IOException */ @Test -- GitLab