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 support for unmodifiable collections - Use safe default typing via a PolymorphicTypeValidator Jackson 3 changes compared to Jackson 2 are documented in https://cowtowncoder.medium.com/jackson-3-0-0-ga-released-1f669cda529a and https://github.com/FasterXML/jackson/blob/main/jackson3/MIGRATING_TO_JACKSON_3.md. 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 <sdeleuze@users.noreply.github.com>
This commit is contained in:
committed by
Rob Winch
parent
916a687b29
commit
65a14d6c6d
@@ -46,6 +46,7 @@ dependencies {
|
||||
optional 'org.springframework:spring-tx'
|
||||
optional 'org.springframework:spring-webflux'
|
||||
optional 'org.springframework:spring-webmvc'
|
||||
optional 'tools.jackson.core:jackson-databind'
|
||||
optional libs.webauthn4j.core
|
||||
|
||||
provided 'jakarta.servlet:jakarta.servlet-api'
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import tools.jackson.core.JacksonException;
|
||||
import tools.jackson.core.JsonParser;
|
||||
import tools.jackson.databind.DeserializationContext;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
import tools.jackson.databind.ValueDeserializer;
|
||||
import tools.jackson.databind.node.MissingNode;
|
||||
import tools.jackson.databind.node.NullNode;
|
||||
|
||||
/**
|
||||
* Jackson deserializer for {@link Cookie}. This is needed because in most cases we don't
|
||||
* set {@link Cookie#getDomain()} property. So when jackson deserialize that json
|
||||
* {@link Cookie#setDomain(String)} throws {@link NullPointerException}. This is
|
||||
* registered with {@link CookieMixin} but you can also use it with your own mixin.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Jitendra Singh
|
||||
* @since 7.0
|
||||
* @see CookieMixin
|
||||
*/
|
||||
class CookieDeserializer extends ValueDeserializer<Cookie> {
|
||||
|
||||
@Override
|
||||
public Cookie deserialize(JsonParser jp, DeserializationContext ctxt) throws JacksonException {
|
||||
JsonNode jsonNode = ctxt.readTree(jp);
|
||||
Cookie cookie = new Cookie(readJsonNode(jsonNode, "name").stringValue(),
|
||||
readJsonNode(jsonNode, "value").stringValue());
|
||||
JsonNode domainNode = readJsonNode(jsonNode, "domain");
|
||||
cookie.setDomain((domainNode.isMissingNode()) ? null : domainNode.stringValue());
|
||||
cookie.setMaxAge(readJsonNode(jsonNode, "maxAge").asInt(-1));
|
||||
cookie.setSecure(readJsonNode(jsonNode, "secure").asBoolean());
|
||||
JsonNode pathNode = readJsonNode(jsonNode, "path");
|
||||
cookie.setPath((pathNode.isMissingNode()) ? null : pathNode.stringValue());
|
||||
JsonNode attributes = readJsonNode(jsonNode, "attributes");
|
||||
cookie.setHttpOnly(readJsonNode(attributes, "HttpOnly") != null);
|
||||
return cookie;
|
||||
}
|
||||
|
||||
private JsonNode readJsonNode(JsonNode jsonNode, String field) {
|
||||
return hasNonNullField(jsonNode, field) ? jsonNode.get(field) : MissingNode.getInstance();
|
||||
}
|
||||
|
||||
private boolean hasNonNullField(JsonNode jsonNode, String field) {
|
||||
return jsonNode.has(field) && !(jsonNode.get(field) instanceof NullNode);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import tools.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
/**
|
||||
* Mixin class to serialize/deserialize {@link jakarta.servlet.http.Cookie}
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Jitendra Singh
|
||||
* @since 7.0
|
||||
* @see WebServletJacksonModule
|
||||
* @see org.springframework.security.jackson.SecurityJacksonModules
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonDeserialize(using = CookieDeserializer.class)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
abstract class CookieMixin {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
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.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Jitendra Singh
|
||||
* @since 7.0
|
||||
* @see WebJacksonModule
|
||||
* @see org.springframework.security.jackson.SecurityJacksonModules
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
class DefaultCsrfTokenMixin {
|
||||
|
||||
/**
|
||||
* JsonCreator constructor needed by Jackson to create
|
||||
* {@link org.springframework.security.web.csrf.DefaultCsrfToken} object.
|
||||
* @param headerName the name of the header
|
||||
* @param parameterName the parameter name
|
||||
* @param token the CSRF token value
|
||||
*/
|
||||
@JsonCreator
|
||||
DefaultCsrfTokenMixin(@JsonProperty("headerName") String headerName,
|
||||
@JsonProperty("parameterName") String parameterName, @JsonProperty("token") String token) {
|
||||
}
|
||||
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import tools.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
import org.springframework.security.web.savedrequest.DefaultSavedRequest;
|
||||
|
||||
/**
|
||||
* Jackson mixin class to serialize/deserialize {@link DefaultSavedRequest}. This mixin
|
||||
* use {@link DefaultSavedRequest.Builder} to deserialized json.In order to use this mixin
|
||||
* class you also need to register {@link CookieMixin}.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Jitendra Singh
|
||||
* @since 7.0
|
||||
* @see WebServletJacksonModule
|
||||
* @see org.springframework.security.jackson.SecurityJacksonModules
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonDeserialize(builder = DefaultSavedRequest.Builder.class)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
abstract class DefaultSavedRequestMixin {
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
String matchingRequestParameterName;
|
||||
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import tools.jackson.core.JacksonException;
|
||||
import tools.jackson.core.JsonParser;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import tools.jackson.databind.DeserializationContext;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
import tools.jackson.databind.ValueDeserializer;
|
||||
import tools.jackson.databind.node.MissingNode;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||
|
||||
/**
|
||||
* Custom deserializer for {@link PreAuthenticatedAuthenticationToken}. At the time of
|
||||
* deserialization it will invoke suitable constructor depending on the value of
|
||||
* <b>authenticated</b> property. It will ensure that the token's state must not change.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Jitendra Singh
|
||||
* @since 7.0
|
||||
* @see PreAuthenticatedAuthenticationTokenMixin
|
||||
*/
|
||||
class PreAuthenticatedAuthenticationTokenDeserializer extends ValueDeserializer<PreAuthenticatedAuthenticationToken> {
|
||||
|
||||
private static final TypeReference<List<GrantedAuthority>> GRANTED_AUTHORITY_LIST = new TypeReference<>() {
|
||||
};
|
||||
|
||||
/**
|
||||
* This method construct {@link PreAuthenticatedAuthenticationToken} object from
|
||||
* serialized json.
|
||||
* @param jp the JsonParser
|
||||
* @param ctxt the DeserializationContext
|
||||
* @return the user
|
||||
* @throws tools.jackson.core.JacksonException if an error during JSON processing
|
||||
* occurs
|
||||
*/
|
||||
@Override
|
||||
public PreAuthenticatedAuthenticationToken deserialize(JsonParser jp, DeserializationContext ctxt)
|
||||
throws JacksonException {
|
||||
JsonNode jsonNode = ctxt.readTree(jp);
|
||||
boolean authenticated = readJsonNode(jsonNode, "authenticated").asBoolean();
|
||||
JsonNode principalNode = readJsonNode(jsonNode, "principal");
|
||||
Object principal = (!principalNode.isObject()) ? principalNode.stringValue()
|
||||
: ctxt.readTreeAsValue(principalNode, Object.class);
|
||||
Object credentials = readJsonNode(jsonNode, "credentials").stringValue();
|
||||
JsonNode authoritiesNode = readJsonNode(jsonNode, "authorities");
|
||||
List<GrantedAuthority> authorities = ctxt.readTreeAsValue(authoritiesNode,
|
||||
ctxt.getTypeFactory().constructType(GRANTED_AUTHORITY_LIST));
|
||||
PreAuthenticatedAuthenticationToken token = (!authenticated)
|
||||
? new PreAuthenticatedAuthenticationToken(principal, credentials)
|
||||
: new PreAuthenticatedAuthenticationToken(principal, credentials, authorities);
|
||||
token.setDetails(readJsonNode(jsonNode, "details"));
|
||||
return token;
|
||||
}
|
||||
|
||||
private JsonNode readJsonNode(JsonNode jsonNode, String field) {
|
||||
return jsonNode.has(field) ? jsonNode.get(field) : MissingNode.getInstance();
|
||||
}
|
||||
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import tools.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
import org.springframework.security.jackson.SecurityJacksonModules;
|
||||
|
||||
/**
|
||||
* This mixin class is used to serialize / deserialize
|
||||
* {@link org.springframework.security.authentication.UsernamePasswordAuthenticationToken}.
|
||||
* This class register a custom deserializer
|
||||
* {@link PreAuthenticatedAuthenticationTokenDeserializer}.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Jitendra Singh
|
||||
* @since 7.0
|
||||
* @see WebJacksonModule
|
||||
* @see SecurityJacksonModules
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonDeserialize(using = PreAuthenticatedAuthenticationTokenDeserializer.class)
|
||||
abstract class PreAuthenticatedAuthenticationTokenMixin {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
/**
|
||||
* Jackson mixin class to serialize/deserialize
|
||||
* {@link org.springframework.security.web.savedrequest.SavedCookie} serialization
|
||||
* support.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Jitendra Singh
|
||||
* @since 7.0
|
||||
* @see WebServletJacksonModule
|
||||
* @see org.springframework.security.jackson.SecurityJacksonModules
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
abstract class SavedCookieMixin {
|
||||
|
||||
@JsonCreator
|
||||
SavedCookieMixin(@JsonProperty("name") String name, @JsonProperty("value") String value,
|
||||
@JsonProperty("domain") String domain, @JsonProperty("maxAge") int maxAge,
|
||||
@JsonProperty("path") String path, @JsonProperty("secure") boolean secure) {
|
||||
}
|
||||
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
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 org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.switchuser.SwitchUserGrantedAuthority;
|
||||
|
||||
/**
|
||||
* Jackson mixin class to serialize/deserialize {@link SwitchUserGrantedAuthority}.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Markus Heiden
|
||||
* @since 7.0
|
||||
* @see WebJacksonModule
|
||||
* @see WebServletJacksonModule
|
||||
* @see org.springframework.security.jackson.SecurityJacksonModules
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
abstract class SwitchUserGrantedAuthorityMixIn {
|
||||
|
||||
@JsonCreator
|
||||
SwitchUserGrantedAuthorityMixIn(@JsonProperty("role") String role, @JsonProperty("source") Authentication source) {
|
||||
}
|
||||
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
/**
|
||||
* Jackson mixin class to serialize/deserialize
|
||||
* {@link org.springframework.security.web.authentication.WebAuthenticationDetails}.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Jitendra Singh
|
||||
* @since 7.0
|
||||
* @see WebServletJacksonModule
|
||||
* @see org.springframework.security.jackson.SecurityJacksonModules
|
||||
*/
|
||||
@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)
|
||||
class WebAuthenticationDetailsMixin {
|
||||
|
||||
@JsonCreator
|
||||
WebAuthenticationDetailsMixin(@JsonProperty("remoteAddress") String remoteAddress,
|
||||
@JsonProperty("sessionId") String sessionId) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import tools.jackson.core.Version;
|
||||
import tools.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
|
||||
|
||||
import org.springframework.security.jackson.SecurityJacksonModule;
|
||||
import org.springframework.security.jackson.SecurityJacksonModules;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||
import org.springframework.security.web.authentication.switchuser.SwitchUserGrantedAuthority;
|
||||
import org.springframework.security.web.csrf.DefaultCsrfToken;
|
||||
import org.springframework.security.web.savedrequest.DefaultSavedRequest;
|
||||
import org.springframework.security.web.savedrequest.SavedCookie;
|
||||
|
||||
/**
|
||||
* Jackson module for spring-security-web. This module register
|
||||
* {@link DefaultCsrfTokenMixin}, {@link PreAuthenticatedAuthenticationTokenMixin} and
|
||||
* {@link SwitchUserGrantedAuthorityMixIn}.
|
||||
*
|
||||
* <p>
|
||||
* The recommended way to configure it is to use {@link SecurityJacksonModules} in order
|
||||
* to enable properly automatic inclusion of type information with related validation.
|
||||
*
|
||||
* <pre>
|
||||
* ClassLoader loader = getClass().getClassLoader();
|
||||
* JsonMapper mapper = JsonMapper.builder()
|
||||
* .addModules(SecurityJacksonModules.getModules(loader))
|
||||
* .build();
|
||||
* </pre>
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Jitendra Singh
|
||||
* @since 7.0
|
||||
* @see SecurityJacksonModules
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class WebJacksonModule extends SecurityJacksonModule {
|
||||
|
||||
public WebJacksonModule() {
|
||||
super(WebJacksonModule.class.getName(), new Version(1, 0, 0, null, null, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configurePolymorphicTypeValidator(BasicPolymorphicTypeValidator.Builder builder) {
|
||||
builder.allowIfSubType(DefaultCsrfToken.class)
|
||||
.allowIfSubType(SavedCookie.class)
|
||||
.allowIfSubType(DefaultSavedRequest.class)
|
||||
.allowIfSubType(WebAuthenticationDetails.class)
|
||||
.allowIfSubType(PreAuthenticatedAuthenticationToken.class)
|
||||
.allowIfSubType(SwitchUserGrantedAuthority.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupModule(SetupContext context) {
|
||||
context.setMixIn(DefaultCsrfToken.class, DefaultCsrfTokenMixin.class);
|
||||
context.setMixIn(PreAuthenticatedAuthenticationToken.class, PreAuthenticatedAuthenticationTokenMixin.class);
|
||||
context.setMixIn(SwitchUserGrantedAuthority.class, SwitchUserGrantedAuthorityMixIn.class);
|
||||
}
|
||||
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import tools.jackson.core.Version;
|
||||
import tools.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
|
||||
|
||||
import org.springframework.security.jackson.SecurityJacksonModule;
|
||||
import org.springframework.security.jackson.SecurityJacksonModules;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||
import org.springframework.security.web.authentication.switchuser.SwitchUserGrantedAuthority;
|
||||
import org.springframework.security.web.savedrequest.DefaultSavedRequest;
|
||||
import org.springframework.security.web.savedrequest.SavedCookie;
|
||||
import org.springframework.security.web.server.csrf.DefaultCsrfToken;
|
||||
|
||||
/**
|
||||
* Jackson module for spring-security-web related to servlet. This module registers
|
||||
* {@link CookieMixin}, {@link SavedCookieMixin}, {@link DefaultSavedRequestMixin},
|
||||
* {@link WebAuthenticationDetailsMixin}, and {@link SwitchUserGrantedAuthorityMixIn}.
|
||||
*
|
||||
* <p>
|
||||
* The recommended way to configure it is to use {@link SecurityJacksonModules} in order
|
||||
* to enable properly automatic inclusion of type information with related validation.
|
||||
*
|
||||
* <pre>
|
||||
* ClassLoader loader = getClass().getClassLoader();
|
||||
* JsonMapper mapper = JsonMapper.builder()
|
||||
* .addModules(SecurityJacksonModules.getModules(loader))
|
||||
* .build();
|
||||
* </pre>
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Boris Finkelshteyn
|
||||
* @since 7.0
|
||||
* @see SecurityJacksonModules
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class WebServletJacksonModule extends SecurityJacksonModule {
|
||||
|
||||
public WebServletJacksonModule() {
|
||||
super(WebServletJacksonModule.class.getName(), new Version(1, 0, 0, null, null, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configurePolymorphicTypeValidator(BasicPolymorphicTypeValidator.Builder builder) {
|
||||
builder.allowIfSubType(Cookie.class).allowIfSubType(DefaultCsrfToken.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupModule(SetupContext context) {
|
||||
context.setMixIn(Cookie.class, CookieMixin.class);
|
||||
context.setMixIn(SavedCookie.class, SavedCookieMixin.class);
|
||||
context.setMixIn(DefaultSavedRequest.class, DefaultSavedRequestMixin.class);
|
||||
context.setMixIn(WebAuthenticationDetails.class, WebAuthenticationDetailsMixin.class);
|
||||
context.setMixIn(SwitchUserGrantedAuthority.class, SwitchUserGrantedAuthorityMixIn.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Jackson 3+ serialization support for web.
|
||||
*/
|
||||
package org.springframework.security.web.jackson;
|
||||
@@ -15,10 +15,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Mix-in classes to provide Jackson serialization support.
|
||||
*
|
||||
* @author Jitendra Singh
|
||||
* @since 4.2
|
||||
* Jackson 2 serialization support for web.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.web.jackson2;
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.server.jackson;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
/**
|
||||
* Jackson mixin class to serialize/deserialize
|
||||
* {@link org.springframework.security.web.server.csrf.DefaultCsrfToken} serialization
|
||||
* support.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Boris Finkelshteyn
|
||||
* @since 7.0
|
||||
* @see WebServerJacksonModule
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
class DefaultCsrfServerTokenMixin {
|
||||
|
||||
/**
|
||||
* JsonCreator constructor needed by Jackson to create
|
||||
* {@link org.springframework.security.web.server.csrf.DefaultCsrfToken} object.
|
||||
* @param headerName the name of the header
|
||||
* @param parameterName the parameter name
|
||||
* @param token the CSRF token value
|
||||
*/
|
||||
@JsonCreator
|
||||
DefaultCsrfServerTokenMixin(@JsonProperty("headerName") String headerName,
|
||||
@JsonProperty("parameterName") String parameterName, @JsonProperty("token") String token) {
|
||||
}
|
||||
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.server.jackson;
|
||||
|
||||
import tools.jackson.core.Version;
|
||||
import tools.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
|
||||
|
||||
import org.springframework.security.jackson.SecurityJacksonModule;
|
||||
import org.springframework.security.jackson.SecurityJacksonModules;
|
||||
import org.springframework.security.web.server.csrf.DefaultCsrfToken;
|
||||
|
||||
/**
|
||||
* Jackson module for spring-security-web-flux. This module register
|
||||
* {@link DefaultCsrfServerTokenMixin}.
|
||||
*
|
||||
* <p>
|
||||
* The recommended way to configure it is to use {@link SecurityJacksonModules} in order
|
||||
* to enable properly automatic inclusion of type information with related validation.
|
||||
*
|
||||
* <pre>
|
||||
* ClassLoader loader = getClass().getClassLoader();
|
||||
* JsonMapper mapper = JsonMapper.builder()
|
||||
* .addModules(SecurityJacksonModules.getModules(loader))
|
||||
* .build();
|
||||
* </pre>
|
||||
*
|
||||
* @author Boris Finkelshteyn
|
||||
* @since 5.1
|
||||
* @see SecurityJacksonModules
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class WebServerJacksonModule extends SecurityJacksonModule {
|
||||
|
||||
private static final String NAME = WebServerJacksonModule.class.getName();
|
||||
|
||||
private static final Version VERSION = new Version(1, 0, 0, null, null, null);
|
||||
|
||||
public WebServerJacksonModule() {
|
||||
super(NAME, VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configurePolymorphicTypeValidator(BasicPolymorphicTypeValidator.Builder builder) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupModule(SetupContext context) {
|
||||
context.setMixIn(DefaultCsrfToken.class, DefaultCsrfServerTokenMixin.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Jackson 3+ serialization support for reactive web server.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.web.server.jackson;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Reactive web jackson2 integration.
|
||||
* Jackson 2 serialization support for reactive web server.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.web.server.jackson2;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import tools.jackson.databind.json.JsonMapper;
|
||||
|
||||
import org.springframework.security.jackson.SecurityJacksonModules;
|
||||
|
||||
/**
|
||||
* @author Sebastien Deleuze
|
||||
* @author Jitenra Singh
|
||||
*/
|
||||
public abstract class AbstractMixinTests {
|
||||
|
||||
protected JsonMapper mapper;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
ClassLoader loader = getClass().getClassLoader();
|
||||
this.mapper = JsonMapper.builder().addModules(SecurityJacksonModules.getModules(loader)).build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import tools.jackson.core.JacksonException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Jitendra Singh
|
||||
* @since 4.2
|
||||
*/
|
||||
public class CookieMixinTests extends AbstractMixinTests {
|
||||
|
||||
// @formatter:off
|
||||
private static final String COOKIE_JSON = "{" +
|
||||
" \"@class\": \"jakarta.servlet.http.Cookie\"," +
|
||||
" \"name\": \"demo\"," +
|
||||
" \"value\": \"cookie1\"," +
|
||||
" \"attributes\":{\"@class\":\"java.util.Collections$EmptyMap\"}," +
|
||||
" \"comment\": null," +
|
||||
" \"maxAge\": -1," +
|
||||
" \"path\": null," +
|
||||
" \"secure\": false," +
|
||||
" \"version\": 0," +
|
||||
" \"domain\": null" +
|
||||
"}";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String COOKIE_HTTP_ONLY_JSON = "{" +
|
||||
" \"@class\": \"jakarta.servlet.http.Cookie\"," +
|
||||
" \"name\": \"demo\"," +
|
||||
" \"value\": \"cookie1\"," +
|
||||
" \"attributes\":{\"@class\":\"java.util.Collections$UnmodifiableMap\", \"HttpOnly\": \"\"}," +
|
||||
" \"comment\": null," +
|
||||
" \"maxAge\": -1," +
|
||||
" \"path\": null," +
|
||||
" \"secure\": false," +
|
||||
" \"version\": 0," +
|
||||
" \"domain\": null" +
|
||||
"}";
|
||||
// @formatter:on
|
||||
|
||||
@Test
|
||||
public void serializeCookie() throws JacksonException, JSONException {
|
||||
Cookie cookie = new Cookie("demo", "cookie1");
|
||||
String actualString = this.mapper.writeValueAsString(cookie);
|
||||
JSONAssert.assertEquals(COOKIE_JSON, actualString, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeCookie() {
|
||||
Cookie cookie = this.mapper.readValue(COOKIE_JSON, Cookie.class);
|
||||
assertThat(cookie).isNotNull();
|
||||
assertThat(cookie.getName()).isEqualTo("demo");
|
||||
assertThat(cookie.getDomain()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeCookieWithHttpOnly() throws JacksonException, JSONException {
|
||||
Cookie cookie = new Cookie("demo", "cookie1");
|
||||
cookie.setHttpOnly(true);
|
||||
String actualString = this.mapper.writeValueAsString(cookie);
|
||||
JSONAssert.assertEquals(COOKIE_HTTP_ONLY_JSON, actualString, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeCookieWithHttpOnly() {
|
||||
Cookie cookie = this.mapper.readValue(COOKIE_HTTP_ONLY_JSON, Cookie.class);
|
||||
assertThat(cookie).isNotNull();
|
||||
assertThat(cookie.getName()).isEqualTo("demo");
|
||||
assertThat(cookie.getDomain()).isNull();
|
||||
assertThat(cookie.isHttpOnly()).isEqualTo(true);
|
||||
}
|
||||
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import tools.jackson.core.JacksonException;
|
||||
|
||||
import org.springframework.security.web.csrf.DefaultCsrfToken;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* @author Jitendra Singh
|
||||
* @since 4.2
|
||||
*/
|
||||
public class DefaultCsrfTokenMixinTests extends AbstractMixinTests {
|
||||
|
||||
// @formatter:off
|
||||
public static final String CSRF_JSON = "{"
|
||||
+ "\"@class\": \"org.springframework.security.web.csrf.DefaultCsrfToken\", "
|
||||
+ "\"headerName\": \"csrf-header\", "
|
||||
+ "\"parameterName\": \"_csrf\", "
|
||||
+ "\"token\": \"1\""
|
||||
+ "}";
|
||||
// @formatter:on
|
||||
@Test
|
||||
public void defaultCsrfTokenSerializedTest() throws JacksonException, JSONException {
|
||||
DefaultCsrfToken token = new DefaultCsrfToken("csrf-header", "_csrf", "1");
|
||||
String serializedJson = this.mapper.writeValueAsString(token);
|
||||
JSONAssert.assertEquals(CSRF_JSON, serializedJson, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultCsrfTokenDeserializeTest() {
|
||||
DefaultCsrfToken token = this.mapper.readValue(CSRF_JSON, DefaultCsrfToken.class);
|
||||
assertThat(token).isNotNull();
|
||||
assertThat(token.getHeaderName()).isEqualTo("csrf-header");
|
||||
assertThat(token.getParameterName()).isEqualTo("_csrf");
|
||||
assertThat(token.getToken()).isEqualTo("1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultCsrfTokenDeserializeWithoutClassTest() {
|
||||
String tokenJson = "{\"headerName\": \"csrf-header\", \"parameterName\": \"_csrf\", \"token\": \"1\"}";
|
||||
assertThatExceptionOfType(JacksonException.class)
|
||||
.isThrownBy(() -> this.mapper.readValue(tokenJson, DefaultCsrfToken.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultCsrfTokenDeserializeNullValuesTest() {
|
||||
String tokenJson = "{\"@class\": \"org.springframework.security.web.csrf.DefaultCsrfToken\", \"headerName\": \"\", \"parameterName\": null, \"token\": \"1\"}";
|
||||
assertThatExceptionOfType(JacksonException.class)
|
||||
.isThrownBy(() -> this.mapper.readValue(tokenJson, DefaultCsrfToken.class));
|
||||
}
|
||||
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.security.web.savedrequest.DefaultSavedRequest;
|
||||
import org.springframework.security.web.savedrequest.SavedCookie;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Jitendra Singh
|
||||
* @since 4.2
|
||||
*/
|
||||
public class DefaultSavedRequestMixinTests extends AbstractMixinTests {
|
||||
|
||||
// @formatter:off
|
||||
private static final String COOKIES_JSON = "[\"java.util.ArrayList\", [{"
|
||||
+ "\"@class\": \"org.springframework.security.web.savedrequest.SavedCookie\", "
|
||||
+ "\"name\": \"SESSION\", "
|
||||
+ "\"value\": \"123456789\", "
|
||||
+ "\"maxAge\": -1, "
|
||||
+ "\"path\": null, "
|
||||
+ "\"secure\":false, "
|
||||
+ "\"domain\": null"
|
||||
+ "}]]";
|
||||
// @formatter:on
|
||||
// @formatter:off
|
||||
private static final String REQUEST_JSON = "{" +
|
||||
"\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", "
|
||||
+ "\"cookies\": " + COOKIES_JSON + ","
|
||||
+ "\"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"
|
||||
+ "}";
|
||||
// @formatter:on
|
||||
// @formatter:off
|
||||
private static final String REQUEST_WITH_MATCHING_REQUEST_PARAM_NAME_JSON = "{" +
|
||||
"\"@class\": \"org.springframework.security.web.savedrequest.DefaultSavedRequest\", "
|
||||
+ "\"cookies\": " + COOKIES_JSON + ","
|
||||
+ "\"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, "
|
||||
+ "\"matchingRequestParameterName\": \"success\""
|
||||
+ "}";
|
||||
// @formatter:on
|
||||
@Test
|
||||
public void matchRequestBuildWithConstructorAndBuilder() {
|
||||
DefaultSavedRequest request = new DefaultSavedRequest.Builder()
|
||||
.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();
|
||||
MockHttpServletRequest mockRequest = new MockHttpServletRequest();
|
||||
mockRequest.setCookies(new Cookie("SESSION", "123456789"));
|
||||
mockRequest.addHeader("x-auth-token", "12");
|
||||
String currentUrl = UrlUtils.buildFullRequestUrl(mockRequest);
|
||||
assertThat(request.getRedirectUrl().equals(currentUrl)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeDefaultRequestBuildWithConstructorTest() throws IOException, JSONException {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("x-auth-token", "12");
|
||||
// Spring 5 MockHttpServletRequest automatically adds a header when the cookies
|
||||
// are set. To get consistency we override the request.
|
||||
HttpServletRequest requestToWrite = new HttpServletRequestWrapper(request) {
|
||||
@Override
|
||||
public Cookie[] getCookies() {
|
||||
return new Cookie[] { new Cookie("SESSION", "123456789") };
|
||||
}
|
||||
};
|
||||
String actualString = this.mapper.writerWithDefaultPrettyPrinter()
|
||||
.writeValueAsString(new DefaultSavedRequest(requestToWrite));
|
||||
JSONAssert.assertEquals(REQUEST_JSON, actualString, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeDefaultRequestBuildWithBuilderTest() throws IOException, JSONException {
|
||||
DefaultSavedRequest request = new DefaultSavedRequest.Builder()
|
||||
.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 actualString = this.mapper.writerWithDefaultPrettyPrinter().writeValueAsString(request);
|
||||
JSONAssert.assertEquals(REQUEST_JSON, actualString, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeDefaultSavedRequest() {
|
||||
DefaultSavedRequest request = (DefaultSavedRequest) this.mapper.readValue(REQUEST_JSON, Object.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 deserializeWhenMatchingRequestParameterNameThenRedirectUrlContainsParam() {
|
||||
DefaultSavedRequest request = (DefaultSavedRequest) this.mapper
|
||||
.readValue(REQUEST_WITH_MATCHING_REQUEST_PARAM_NAME_JSON, Object.class);
|
||||
assertThat(request.getRedirectUrl()).isEqualTo("http://localhost?success");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeWhenNullMatchingRequestParameterNameThenRedirectUrlDoesNotContainParam() {
|
||||
DefaultSavedRequest request = (DefaultSavedRequest) this.mapper.readValue(REQUEST_JSON, Object.class);
|
||||
assertThat(request.getRedirectUrl()).isEqualTo("http://localhost");
|
||||
}
|
||||
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import tools.jackson.core.JacksonException;
|
||||
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.jackson2.SimpleGrantedAuthorityMixinTests;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 4.2
|
||||
*/
|
||||
public class PreAuthenticatedAuthenticationTokenMixinTests extends AbstractMixinTests {
|
||||
|
||||
// @formatter:off
|
||||
private static final String PREAUTH_JSON = "{"
|
||||
+ "\"@class\": \"org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken\","
|
||||
+ "\"principal\": \"principal\", "
|
||||
+ "\"credentials\": \"credentials\", "
|
||||
+ "\"authenticated\": true, "
|
||||
+ "\"details\": null, "
|
||||
+ "\"authorities\": " + SimpleGrantedAuthorityMixinTests.AUTHORITIES_ARRAYLIST_JSON
|
||||
+ "}";
|
||||
// @formatter:on
|
||||
PreAuthenticatedAuthenticationToken expected;
|
||||
|
||||
@BeforeEach
|
||||
public void setupExpected() {
|
||||
this.expected = new PreAuthenticatedAuthenticationToken("principal", "credentials",
|
||||
AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeWhenPrincipalCredentialsAuthoritiesThenSuccess() throws JacksonException, JSONException {
|
||||
String serializedJson = this.mapper.writeValueAsString(this.expected);
|
||||
JSONAssert.assertEquals(PREAUTH_JSON, serializedJson, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenMixinTest() {
|
||||
PreAuthenticatedAuthenticationToken deserialized = this.mapper.readValue(PREAUTH_JSON,
|
||||
PreAuthenticatedAuthenticationToken.class);
|
||||
assertThat(deserialized).isNotNull();
|
||||
assertThat(deserialized.isAuthenticated()).isTrue();
|
||||
assertThat(deserialized.getAuthorities()).isEqualTo(this.expected.getAuthorities());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import tools.jackson.core.JacksonException;
|
||||
|
||||
import org.springframework.security.web.savedrequest.SavedCookie;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Jitendra Singh
|
||||
*/
|
||||
public class SavedCookieMixinTests extends AbstractMixinTests {
|
||||
|
||||
// @formatter:off
|
||||
private static final String COOKIE_JSON = "{"
|
||||
+ "\"@class\": \"org.springframework.security.web.savedrequest.SavedCookie\", "
|
||||
+ "\"name\": \"SESSION\", "
|
||||
+ "\"value\": \"123456789\", "
|
||||
+ "\"maxAge\": -1, "
|
||||
+ "\"path\": null, "
|
||||
+ "\"secure\":false, "
|
||||
+ "\"domain\": null"
|
||||
+ "}";
|
||||
// @formatter:on
|
||||
// @formatter:off
|
||||
private static final String COOKIES_JSON = "[\"java.util.ArrayList\", ["
|
||||
+ COOKIE_JSON
|
||||
+ "]]";
|
||||
// @formatter:on
|
||||
@Test
|
||||
public void serializeWithDefaultConfigurationTest() throws JacksonException, JSONException {
|
||||
SavedCookie savedCookie = new SavedCookie(new Cookie("SESSION", "123456789"));
|
||||
String actualJson = this.mapper.writeValueAsString(savedCookie);
|
||||
JSONAssert.assertEquals(COOKIE_JSON, actualJson, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("No supported by Jackson 3 as ObjectMapper/JsonMapper is immutable")
|
||||
public void serializeWithOverrideConfigurationTest() throws JacksonException, JSONException {
|
||||
SavedCookie savedCookie = new SavedCookie(new Cookie("SESSION", "123456789"));
|
||||
// this.mapper.setVisibility(PropertyAccessor.FIELD,
|
||||
// JsonAutoDetect.Visibility.PUBLIC_ONLY)
|
||||
// .setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY);
|
||||
String actualJson = this.mapper.writeValueAsString(savedCookie);
|
||||
JSONAssert.assertEquals(COOKIE_JSON, actualJson, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeSavedCookieWithList() throws JacksonException, JSONException {
|
||||
List<SavedCookie> savedCookies = new ArrayList<>();
|
||||
savedCookies.add(new SavedCookie(new Cookie("SESSION", "123456789")));
|
||||
String actualJson = this.mapper.writeValueAsString(savedCookies);
|
||||
JSONAssert.assertEquals(COOKIES_JSON, actualJson, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void deserializeSavedCookieWithList() {
|
||||
List<SavedCookie> savedCookies = (List<SavedCookie>) this.mapper.readValue(COOKIES_JSON, Object.class);
|
||||
assertThat(savedCookies).isNotNull().hasSize(1);
|
||||
assertThat(savedCookies.get(0).getName()).isEqualTo("SESSION");
|
||||
assertThat(savedCookies.get(0).getValue()).isEqualTo("123456789");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeSavedCookieJsonTest() {
|
||||
SavedCookie savedCookie = (SavedCookie) this.mapper.readValue(COOKIE_JSON, Object.class);
|
||||
assertThat(savedCookie).isNotNull();
|
||||
assertThat(savedCookie.getName()).isEqualTo("SESSION");
|
||||
assertThat(savedCookie.getValue()).isEqualTo("123456789");
|
||||
assertThat(savedCookie.isSecure()).isEqualTo(false);
|
||||
}
|
||||
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import tools.jackson.databind.json.JsonMapper;
|
||||
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.jackson.SecurityJacksonModules;
|
||||
import org.springframework.security.jackson.SimpleGrantedAuthorityMixinTests;
|
||||
import org.springframework.security.web.authentication.switchuser.SwitchUserGrantedAuthority;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Markus Heiden
|
||||
* @since 6.3
|
||||
*/
|
||||
public class SwitchUserGrantedAuthorityMixInTests {
|
||||
|
||||
// language=JSON
|
||||
private static final String SWITCH_JSON = """
|
||||
{
|
||||
"@class": "org.springframework.security.web.authentication.switchuser.SwitchUserGrantedAuthority",
|
||||
"role": "switched",
|
||||
"source": {
|
||||
"@class": "org.springframework.security.authentication.UsernamePasswordAuthenticationToken",
|
||||
"principal": "principal",
|
||||
"credentials": "credentials",
|
||||
"authenticated": true,
|
||||
"details": null,
|
||||
"authorities": %s
|
||||
}
|
||||
}
|
||||
""".formatted(SimpleGrantedAuthorityMixinTests.AUTHORITIES_ARRAYLIST_JSON);
|
||||
|
||||
private Authentication source;
|
||||
|
||||
private JsonMapper mapper;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
this.source = new UsernamePasswordAuthenticationToken("principal", "credentials",
|
||||
AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
ClassLoader classLoader = SwitchUserGrantedAuthorityMixInTests.class.getClassLoader();
|
||||
this.mapper = JsonMapper.builder().addModules(SecurityJacksonModules.getModules(classLoader)).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeWhenPrincipalCredentialsAuthoritiesThenSuccess() throws Exception {
|
||||
SwitchUserGrantedAuthority expected = new SwitchUserGrantedAuthority("switched", this.source);
|
||||
String serializedJson = this.mapper.writeValueAsString(expected);
|
||||
JSONAssert.assertEquals(SWITCH_JSON, serializedJson, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserializeWhenSourceIsUsernamePasswordAuthenticationTokenThenSuccess() {
|
||||
SwitchUserGrantedAuthority deserialized = this.mapper.readValue(SWITCH_JSON, SwitchUserGrantedAuthority.class);
|
||||
assertThat(deserialized).isNotNull();
|
||||
assertThat(deserialized.getAuthority()).isEqualTo("switched");
|
||||
assertThat(deserialized.getSource()).isEqualTo(this.source);
|
||||
}
|
||||
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.jackson;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import tools.jackson.core.JacksonException;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Jitendra Singh
|
||||
* @since 4.2
|
||||
*/
|
||||
public class WebAuthenticationDetailsMixinTests extends AbstractMixinTests {
|
||||
|
||||
// @formatter:off
|
||||
private static final String AUTHENTICATION_DETAILS_JSON = "{"
|
||||
+ "\"@class\": \"org.springframework.security.web.authentication.WebAuthenticationDetails\","
|
||||
+ "\"sessionId\": \"1\", "
|
||||
+ "\"remoteAddress\": "
|
||||
+ "\"/localhost\""
|
||||
+ "}";
|
||||
// @formatter:on
|
||||
@Test
|
||||
public void buildWebAuthenticationDetailsUsingDifferentConstructors() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRemoteAddr("localhost");
|
||||
request.setSession(new MockHttpSession(null, "1"));
|
||||
WebAuthenticationDetails details = new WebAuthenticationDetails(request);
|
||||
WebAuthenticationDetails authenticationDetails = this.mapper.readValue(AUTHENTICATION_DETAILS_JSON,
|
||||
WebAuthenticationDetails.class);
|
||||
assertThat(details.equals(authenticationDetails));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void webAuthenticationDetailsSerializeTest() throws JacksonException, JSONException {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRemoteAddr("/localhost");
|
||||
request.setSession(new MockHttpSession(null, "1"));
|
||||
WebAuthenticationDetails details = new WebAuthenticationDetails(request);
|
||||
String actualJson = this.mapper.writeValueAsString(details);
|
||||
JSONAssert.assertEquals(AUTHENTICATION_DETAILS_JSON, actualJson, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void webAuthenticationDetailsJackson2SerializeTest() throws JacksonException, JSONException {
|
||||
WebAuthenticationDetails details = new WebAuthenticationDetails("/localhost", "1");
|
||||
String actualJson = this.mapper.writeValueAsString(details);
|
||||
JSONAssert.assertEquals(AUTHENTICATION_DETAILS_JSON, actualJson, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void webAuthenticationDetailsDeserializeTest() {
|
||||
WebAuthenticationDetails details = this.mapper.readValue(AUTHENTICATION_DETAILS_JSON,
|
||||
WebAuthenticationDetails.class);
|
||||
assertThat(details).isNotNull();
|
||||
assertThat(details.getRemoteAddress()).isEqualTo("/localhost");
|
||||
assertThat(details.getSessionId()).isEqualTo("1");
|
||||
}
|
||||
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.server.jackson;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import tools.jackson.core.JacksonException;
|
||||
|
||||
import org.springframework.security.web.jackson.AbstractMixinTests;
|
||||
import org.springframework.security.web.server.csrf.DefaultCsrfToken;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* @author Sebastien Deleuze
|
||||
* @author Boris Finkelshteyn
|
||||
*/
|
||||
public class DefaultCsrfServerTokenMixinTests extends AbstractMixinTests {
|
||||
|
||||
// @formatter:off
|
||||
private static final String CSRF_JSON = "{"
|
||||
+ "\"@class\": \"org.springframework.security.web.server.csrf.DefaultCsrfToken\", "
|
||||
+ "\"headerName\": \"csrf-header\", "
|
||||
+ "\"parameterName\": \"_csrf\", "
|
||||
+ "\"token\": \"1\""
|
||||
+ "}";
|
||||
// @formatter:on
|
||||
@Test
|
||||
public void defaultCsrfTokenSerializedTest() throws JacksonException, JSONException {
|
||||
DefaultCsrfToken token = new DefaultCsrfToken("csrf-header", "_csrf", "1");
|
||||
String serializedJson = this.mapper.writeValueAsString(token);
|
||||
JSONAssert.assertEquals(CSRF_JSON, serializedJson, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultCsrfTokenDeserializeTest() throws IOException {
|
||||
DefaultCsrfToken token = this.mapper.readValue(CSRF_JSON, DefaultCsrfToken.class);
|
||||
assertThat(token).isNotNull();
|
||||
assertThat(token.getHeaderName()).isEqualTo("csrf-header");
|
||||
assertThat(token.getParameterName()).isEqualTo("_csrf");
|
||||
assertThat(token.getToken()).isEqualTo("1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultCsrfTokenDeserializeWithoutClassTest() throws IOException {
|
||||
String tokenJson = "{\"headerName\": \"csrf-header\", \"parameterName\": \"_csrf\", \"token\": \"1\"}";
|
||||
assertThatExceptionOfType(JacksonException.class)
|
||||
.isThrownBy(() -> this.mapper.readValue(tokenJson, DefaultCsrfToken.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultCsrfTokenDeserializeNullValuesTest() throws IOException {
|
||||
String tokenJson = "{\"@class\": \"org.springframework.security.web.server.csrf.DefaultCsrfToken\", \"headerName\": \"\", \"parameterName\": null, \"token\": \"1\"}";
|
||||
assertThatExceptionOfType(JacksonException.class)
|
||||
.isThrownBy(() -> this.mapper.readValue(tokenJson, DefaultCsrfToken.class));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user