Skip to content

Commit 0338317

Browse files
committed
Stop CoreJacksonModule from overriding user DateTimeFeature configuration
Remove the global DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS override from CoreJacksonModule.setupModule() and use @jsonformat(shape = NUMBER) on Mixin parameters/getters that need timestamp format for backward compatibility. Closes gh-18561 Signed-off-by: hanweiwei <duzielww@163.com>
1 parent 1455798 commit 0338317

File tree

6 files changed

+58
-9
lines changed

6 files changed

+58
-9
lines changed

core/src/main/java/org/springframework/security/jackson/CoreJacksonModule.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
import java.time.Instant;
2121

2222
import tools.jackson.core.Version;
23-
import tools.jackson.databind.cfg.DateTimeFeature;
24-
import tools.jackson.databind.cfg.MapperBuilder;
2523
import tools.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
2624

2725
import org.springframework.security.authentication.AnonymousAuthenticationToken;
@@ -101,7 +99,6 @@ public void configurePolymorphicTypeValidator(BasicPolymorphicTypeValidator.Buil
10199

102100
@Override
103101
public void setupModule(SetupContext context) {
104-
((MapperBuilder<?, ?>) context.getOwner()).enable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS);
105102
context.setMixIn(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class);
106103
context.setMixIn(RememberMeAuthenticationToken.class, RememberMeAuthenticationTokenMixin.class);
107104
context.setMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);

core/src/main/java/org/springframework/security/jackson/FactorGrantedAuthorityMixin.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import com.fasterxml.jackson.annotation.JsonAutoDetect;
2222
import com.fasterxml.jackson.annotation.JsonCreator;
23+
import com.fasterxml.jackson.annotation.JsonFormat;
2324
import com.fasterxml.jackson.annotation.JsonProperty;
2425
import com.fasterxml.jackson.annotation.JsonTypeInfo;
2526

@@ -44,7 +45,10 @@ abstract class FactorGrantedAuthorityMixin {
4445
*/
4546
@JsonCreator
4647
FactorGrantedAuthorityMixin(@JsonProperty("authority") String authority,
47-
@JsonProperty("issuedAt") Instant issuedAt) {
48+
@JsonProperty("issuedAt") @JsonFormat(shape = JsonFormat.Shape.NUMBER) Instant issuedAt) {
4849
}
4950

51+
@JsonFormat(shape = JsonFormat.Shape.NUMBER)
52+
abstract Instant getIssuedAt();
53+
5054
}

core/src/test/java/org/springframework/security/jackson/FactorGrantedAuthorityMixinTests.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
import org.json.JSONException;
2222
import org.junit.jupiter.api.Test;
2323
import org.skyscreamer.jsonassert.JSONAssert;
24+
import tools.jackson.databind.cfg.DateTimeFeature;
25+
import tools.jackson.databind.json.JsonMapper;
26+
import tools.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
2427

2528
import org.springframework.security.core.GrantedAuthority;
2629
import org.springframework.security.core.authority.FactorGrantedAuthority;
@@ -57,4 +60,41 @@ void deserializeGrantedAuthorityTest() {
5760
assertThat(authority.getIssuedAt()).isEqualTo(this.issuedAt);
5861
}
5962

63+
@Test
64+
void serializeWhenWriteDatesAsTimestampsDisabledThenStillUsesTimestamps() throws JSONException {
65+
ClassLoader loader = getClass().getClassLoader();
66+
JsonMapper customMapper = JsonMapper.builder()
67+
.disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
68+
.addModules(SecurityJacksonModules.getModules(loader, BasicPolymorphicTypeValidator.builder()))
69+
.build();
70+
GrantedAuthority authority = FactorGrantedAuthority.withAuthority("FACTOR_PASSWORD")
71+
.issuedAt(this.issuedAt)
72+
.build();
73+
String json = customMapper.writeValueAsString(authority);
74+
JSONAssert.assertEquals(AUTHORITY_JSON, json, true);
75+
}
76+
77+
@Test
78+
void deserializeWhenWriteDatesAsTimestampsDisabledThenStillDeserializesTimestamps() {
79+
ClassLoader loader = getClass().getClassLoader();
80+
JsonMapper customMapper = JsonMapper.builder()
81+
.disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
82+
.addModules(SecurityJacksonModules.getModules(loader, BasicPolymorphicTypeValidator.builder()))
83+
.build();
84+
FactorGrantedAuthority authority = (FactorGrantedAuthority) customMapper.readValue(AUTHORITY_JSON, Object.class);
85+
assertThat(authority).isNotNull();
86+
assertThat(authority.getAuthority()).isEqualTo("FACTOR_PASSWORD");
87+
assertThat(authority.getIssuedAt()).isEqualTo(this.issuedAt);
88+
}
89+
90+
@Test
91+
void serializeDoesNotOverrideGlobalDateTimeFeature() {
92+
ClassLoader loader = getClass().getClassLoader();
93+
JsonMapper customMapper = JsonMapper.builder()
94+
.disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
95+
.addModules(SecurityJacksonModules.getModules(loader, BasicPolymorphicTypeValidator.builder()))
96+
.build();
97+
assertThat(customMapper.isEnabled(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)).isFalse();
98+
}
99+
60100
}

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson/OAuth2AccessTokenMixin.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import com.fasterxml.jackson.annotation.JsonAutoDetect;
2323
import com.fasterxml.jackson.annotation.JsonCreator;
24+
import com.fasterxml.jackson.annotation.JsonFormat;
2425
import com.fasterxml.jackson.annotation.JsonProperty;
2526
import com.fasterxml.jackson.annotation.JsonTypeInfo;
2627
import tools.jackson.databind.annotation.JsonDeserialize;
@@ -45,8 +46,10 @@ abstract class OAuth2AccessTokenMixin {
4546
OAuth2AccessTokenMixin(
4647
@JsonProperty("tokenType") @JsonDeserialize(
4748
converter = StdConverters.AccessTokenTypeConverter.class) OAuth2AccessToken.TokenType tokenType,
48-
@JsonProperty("tokenValue") String tokenValue, @JsonProperty("issuedAt") Instant issuedAt,
49-
@JsonProperty("expiresAt") Instant expiresAt, @JsonProperty("scopes") Set<String> scopes) {
49+
@JsonProperty("tokenValue") String tokenValue,
50+
@JsonProperty("issuedAt") @JsonFormat(shape = JsonFormat.Shape.NUMBER) Instant issuedAt,
51+
@JsonProperty("expiresAt") @JsonFormat(shape = JsonFormat.Shape.NUMBER) Instant expiresAt,
52+
@JsonProperty("scopes") Set<String> scopes) {
5053
}
5154

5255
}

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson/OAuth2RefreshTokenMixin.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import com.fasterxml.jackson.annotation.JsonAutoDetect;
2222
import com.fasterxml.jackson.annotation.JsonCreator;
23+
import com.fasterxml.jackson.annotation.JsonFormat;
2324
import com.fasterxml.jackson.annotation.JsonProperty;
2425
import com.fasterxml.jackson.annotation.JsonTypeInfo;
2526

@@ -40,7 +41,8 @@
4041
abstract class OAuth2RefreshTokenMixin {
4142

4243
@JsonCreator
43-
OAuth2RefreshTokenMixin(@JsonProperty("tokenValue") String tokenValue, @JsonProperty("issuedAt") Instant issuedAt) {
44+
OAuth2RefreshTokenMixin(@JsonProperty("tokenValue") String tokenValue,
45+
@JsonProperty("issuedAt") @JsonFormat(shape = JsonFormat.Shape.NUMBER) Instant issuedAt) {
4446
}
4547

4648
}

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson/OidcIdTokenMixin.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import com.fasterxml.jackson.annotation.JsonAutoDetect;
2323
import com.fasterxml.jackson.annotation.JsonCreator;
24+
import com.fasterxml.jackson.annotation.JsonFormat;
2425
import com.fasterxml.jackson.annotation.JsonProperty;
2526
import com.fasterxml.jackson.annotation.JsonTypeInfo;
2627

@@ -41,8 +42,10 @@
4142
abstract class OidcIdTokenMixin {
4243

4344
@JsonCreator
44-
OidcIdTokenMixin(@JsonProperty("tokenValue") String tokenValue, @JsonProperty("issuedAt") Instant issuedAt,
45-
@JsonProperty("expiresAt") Instant expiresAt, @JsonProperty("claims") Map<String, Object> claims) {
45+
OidcIdTokenMixin(@JsonProperty("tokenValue") String tokenValue,
46+
@JsonProperty("issuedAt") @JsonFormat(shape = JsonFormat.Shape.NUMBER) Instant issuedAt,
47+
@JsonProperty("expiresAt") @JsonFormat(shape = JsonFormat.Shape.NUMBER) Instant expiresAt,
48+
@JsonProperty("claims") Map<String, Object> claims) {
4649
}
4750

4851
}

0 commit comments

Comments
 (0)