Skip to content

Commit e49a425

Browse files
committed
Add Jackson 3 support
This commit adds support for Jackson 3 which has the following major differences with the Jackson 2 one: - jackson subpackage instead of jackson2 - Jackson type prefix instead of Jackson2 - JsonMapper instead of ObjectMapper - For configuration, JsonMapper.Builder instead of ObjectMapper since the latter is now immutable - Remove custom Jackson 3 support for unmodifiable collections - AllowlistTypeResolverBuilder in new a public type in order to be used easily with the JsonMapper.Builder API Jackson 3 changes compared to Jackson 2 are documented on FasterXML/jackson-future-ideas#72. This commit does not cover webauthn which is a special case (uses jackson sub-package for Jackson 2 support) which will be handled in a distinct commit. See gh-17832 Signed-off-by: Sébastien Deleuze <[email protected]>
1 parent 4413722 commit e49a425

File tree

133 files changed

+8560
-115
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

133 files changed

+8560
-115
lines changed

.idea/checkstyle-idea.xml

Lines changed: 10 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cas/spring-security-cas.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ dependencies {
1515
api 'org.springframework:spring-web'
1616

1717
optional 'com.fasterxml.jackson.core:jackson-databind'
18+
optional 'tools.jackson.core:jackson-databind'
1819

1920
provided 'jakarta.servlet:jakarta.servlet-api'
2021

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2004-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.cas.jackson;
18+
19+
import java.util.Date;
20+
import java.util.Map;
21+
22+
import com.fasterxml.jackson.annotation.JsonAutoDetect;
23+
import com.fasterxml.jackson.annotation.JsonCreator;
24+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
25+
import com.fasterxml.jackson.annotation.JsonProperty;
26+
import com.fasterxml.jackson.annotation.JsonTypeInfo;
27+
import org.apereo.cas.client.authentication.AttributePrincipal;
28+
29+
/**
30+
* Helps in jackson deserialization of class
31+
* {@link org.apereo.cas.client.validation.AssertionImpl}, which is used with
32+
* {@link org.springframework.security.cas.authentication.CasAuthenticationToken}. To use
33+
* this class we need to register with {@link tools.jackson.databind.json.JsonMapper}.
34+
* Type information will be stored in @class property.
35+
* <p>
36+
* <pre>
37+
* JsonMapper mapper = JsonMapper.builder()
38+
* .addModule(new CasJacksonModule())
39+
* .build();
40+
* </pre>
41+
*
42+
* @author Sebastien Deleuze
43+
* @author Jitendra Singh
44+
* @since 7.0
45+
* @see CasJacksonModule
46+
* @see org.springframework.security.jackson.SecurityJacksonModules
47+
*/
48+
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
49+
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
50+
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
51+
@JsonIgnoreProperties(ignoreUnknown = true)
52+
class AssertionImplMixin {
53+
54+
/**
55+
* Mixin Constructor helps in deserialize
56+
* {@link org.apereo.cas.client.validation.AssertionImpl}
57+
* @param principal the Principal to associate with the Assertion.
58+
* @param validFromDate when the assertion is valid from.
59+
* @param validUntilDate when the assertion is valid to.
60+
* @param authenticationDate when the assertion is authenticated.
61+
* @param attributes the key/value pairs for this attribute.
62+
*/
63+
@JsonCreator
64+
AssertionImplMixin(@JsonProperty("principal") AttributePrincipal principal,
65+
@JsonProperty("validFromDate") Date validFromDate, @JsonProperty("validUntilDate") Date validUntilDate,
66+
@JsonProperty("authenticationDate") Date authenticationDate,
67+
@JsonProperty("attributes") Map<String, Object> attributes) {
68+
}
69+
70+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2004-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.cas.jackson;
18+
19+
import java.util.Map;
20+
21+
import com.fasterxml.jackson.annotation.JsonAutoDetect;
22+
import com.fasterxml.jackson.annotation.JsonCreator;
23+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
24+
import com.fasterxml.jackson.annotation.JsonProperty;
25+
import com.fasterxml.jackson.annotation.JsonTypeInfo;
26+
import org.apereo.cas.client.proxy.ProxyRetriever;
27+
28+
/**
29+
* Helps in deserialize
30+
* {@link org.apereo.cas.client.authentication.AttributePrincipalImpl} which is used with
31+
* {@link org.springframework.security.cas.authentication.CasAuthenticationToken}. Type
32+
* information will be stored in property named @class.
33+
* <p>
34+
* <pre>
35+
* JsonMapper mapper = JsonMapper.builder()
36+
* .addModule(new CasJacksonModule())
37+
* .build();
38+
* </pre>
39+
*
40+
* @author Sebastien Deleuze
41+
* @author Jitendra Singh
42+
* @since 7.0
43+
* @see CasJacksonModule
44+
* @see org.springframework.security.jackson.SecurityJacksonModules
45+
*/
46+
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
47+
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
48+
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
49+
@JsonIgnoreProperties(ignoreUnknown = true)
50+
class AttributePrincipalImplMixin {
51+
52+
/**
53+
* Mixin Constructor helps in deserialize
54+
* {@link org.apereo.cas.client.authentication.AttributePrincipalImpl}
55+
* @param name the unique identifier for the principal.
56+
* @param attributes the key/value pairs for this principal.
57+
* @param proxyGrantingTicket the ticket associated with this principal.
58+
* @param proxyRetriever the ProxyRetriever implementation to call back to the CAS
59+
* server.
60+
*/
61+
@JsonCreator
62+
AttributePrincipalImplMixin(@JsonProperty("name") String name,
63+
@JsonProperty("attributes") Map<String, Object> attributes,
64+
@JsonProperty("proxyGrantingTicket") String proxyGrantingTicket,
65+
@JsonProperty("proxyRetriever") ProxyRetriever proxyRetriever) {
66+
}
67+
68+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright 2004-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.cas.jackson;
18+
19+
import java.util.Collection;
20+
21+
import com.fasterxml.jackson.annotation.JsonAutoDetect;
22+
import com.fasterxml.jackson.annotation.JsonCreator;
23+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
24+
import com.fasterxml.jackson.annotation.JsonProperty;
25+
import com.fasterxml.jackson.annotation.JsonTypeInfo;
26+
import org.apereo.cas.client.validation.Assertion;
27+
28+
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
29+
import org.springframework.security.cas.authentication.CasAuthenticationToken;
30+
import org.springframework.security.core.GrantedAuthority;
31+
import org.springframework.security.core.userdetails.UserDetails;
32+
33+
/**
34+
* Mixin class which helps in deserialize {@link CasAuthenticationToken} using jackson.
35+
* Two more dependent classes needs to register along with this mixin class.
36+
* <ol>
37+
* <li>{@link AssertionImplMixin}</li>
38+
* <li>{@link AttributePrincipalImplMixin}</li>
39+
* </ol>
40+
*
41+
* <p>
42+
*
43+
* <pre>
44+
* JsonMapper mapper = JsonMapper.builder()
45+
* .addModule(new CasJacksonModule())
46+
* .build();
47+
* </pre>
48+
*
49+
* @author Sebastien Deleuze
50+
* @author Jitendra Singh
51+
* @since 7.0
52+
* @see CasJacksonModule
53+
* @see org.springframework.security.jackson.SecurityJacksonModules
54+
*/
55+
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
56+
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE,
57+
getterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.ANY)
58+
@JsonIgnoreProperties(ignoreUnknown = true)
59+
class CasAuthenticationTokenMixin {
60+
61+
/**
62+
* Mixin Constructor helps in deserialize {@link CasAuthenticationToken}
63+
* @param keyHash hashCode of provided key to identify if this object made by a given
64+
* {@link CasAuthenticationProvider}
65+
* @param principal typically the UserDetails object (cannot be <code>null</code>)
66+
* @param credentials the service/proxy ticket ID from CAS (cannot be
67+
* <code>null</code>)
68+
* @param authorities the authorities granted to the user (from the
69+
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
70+
* be <code>null</code>)
71+
* @param userDetails the user details (from the
72+
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
73+
* be <code>null</code>)
74+
* @param assertion the assertion returned from the CAS servers. It contains the
75+
* principal and how to obtain a proxy ticket for the user.
76+
*/
77+
@JsonCreator
78+
CasAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal,
79+
@JsonProperty("credentials") Object credentials,
80+
@JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities,
81+
@JsonProperty("userDetails") UserDetails userDetails, @JsonProperty("assertion") Assertion assertion) {
82+
}
83+
84+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2004-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.cas.jackson;
18+
19+
import org.apereo.cas.client.authentication.AttributePrincipalImpl;
20+
import org.apereo.cas.client.validation.AssertionImpl;
21+
import tools.jackson.core.Version;
22+
import tools.jackson.databind.cfg.MapperBuilder;
23+
import tools.jackson.databind.module.SimpleModule;
24+
25+
import org.springframework.security.cas.authentication.CasAuthenticationToken;
26+
import org.springframework.security.jackson.AllowlistTypeResolverBuilder;
27+
import org.springframework.security.jackson.SecurityJacksonModules;
28+
29+
/**
30+
* Jackson module for spring-security-cas. This module register
31+
* {@link AssertionImplMixin}, {@link AttributePrincipalImplMixin} and
32+
* {@link CasAuthenticationTokenMixin}. If no default typing enabled by default then it'll
33+
* enable it because typing info is needed to properly serialize/deserialize objects. In
34+
* order to use this module just add this module into your JsonMapper configuration.
35+
*
36+
* <pre>
37+
* JsonMapper mapper = JsonMapper.builder()
38+
* .addModule(new CasJacksonModule())
39+
* .build();
40+
* </pre>
41+
*
42+
* <b>Note: use {@link SecurityJacksonModules#getModules(ClassLoader)} to get list of all
43+
* security modules on the classpath.</b>
44+
*
45+
* @author Sebastien Deleuze
46+
* @author Jitendra Singh
47+
* @since 7.0
48+
* @see SecurityJacksonModules
49+
*/
50+
public class CasJacksonModule extends SimpleModule {
51+
52+
public CasJacksonModule() {
53+
super(CasJacksonModule.class.getName(), new Version(1, 0, 0, null, null, null));
54+
}
55+
56+
@Override
57+
public void setupModule(SetupContext context) {
58+
((MapperBuilder<?, ?>) context.getOwner()).setDefaultTyping(new AllowlistTypeResolverBuilder());
59+
context.setMixIn(AssertionImpl.class, AssertionImplMixin.class);
60+
context.setMixIn(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class);
61+
context.setMixIn(CasAuthenticationToken.class, CasAuthenticationTokenMixin.class);
62+
}
63+
64+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2004-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Jackson 3+ serialization support for CAS.
19+
*/
20+
package org.springframework.security.cas.jackson;

cas/src/main/java/org/springframework/security/cas/jackson2/package-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
/**
18-
* Jackson support for CAS.
18+
* Jackson 2 support for CAS.
1919
*/
2020
@NullMarked
2121
package org.springframework.security.cas.jackson2;

0 commit comments

Comments
 (0)