diff --git a/web/src/main/java/org/springframework/security/web/http/GenericHttpMessageConverterAdapter.java b/web/src/main/java/org/springframework/security/web/http/GenericHttpMessageConverterAdapter.java deleted file mode 100644 index de3875157f..0000000000 --- a/web/src/main/java/org/springframework/security/web/http/GenericHttpMessageConverterAdapter.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.http; - -import java.io.IOException; -import java.lang.reflect.Type; -import java.util.List; - -import org.jspecify.annotations.Nullable; - -import org.springframework.core.ResolvableType; -import org.springframework.http.HttpInputMessage; -import org.springframework.http.HttpOutputMessage; -import org.springframework.http.MediaType; -import org.springframework.http.converter.GenericHttpMessageConverter; -import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.http.converter.HttpMessageNotWritableException; -import org.springframework.http.converter.SmartHttpMessageConverter; - -/** - * {@link GenericHttpMessageConverter} implementation that delegates to a - * {@link SmartHttpMessageConverter}. - * - * @param the converted object type - * @author Sebastien Deleuze - * @since 7.0 - */ -public class GenericHttpMessageConverterAdapter implements GenericHttpMessageConverter { - - private final SmartHttpMessageConverter smartConverter; - - public GenericHttpMessageConverterAdapter(SmartHttpMessageConverter smartConverter) { - this.smartConverter = smartConverter; - } - - @Override - public boolean canRead(Type type, @Nullable Class contextClass, @Nullable MediaType mediaType) { - return this.smartConverter.canRead(ResolvableType.forType(type), mediaType); - } - - @Override - public T read(Type type, @Nullable Class contextClass, HttpInputMessage inputMessage) - throws IOException, HttpMessageNotReadableException { - return this.smartConverter.read(ResolvableType.forType(type), inputMessage, null); - } - - @Override - public boolean canWrite(@Nullable Type type, Class clazz, @Nullable MediaType mediaType) { - return this.smartConverter.canWrite(ResolvableType.forType(type), clazz, mediaType); - } - - @Override - public void write(T t, @Nullable Type type, @Nullable MediaType contentType, HttpOutputMessage outputMessage) - throws IOException, HttpMessageNotWritableException { - this.smartConverter.write(t, ResolvableType.forType(type), contentType, outputMessage, null); - } - - @Override - public boolean canRead(Class clazz, @Nullable MediaType mediaType) { - return this.smartConverter.canRead(ResolvableType.forClass(clazz), mediaType); - } - - @Override - public boolean canWrite(Class clazz, @Nullable MediaType mediaType) { - return this.smartConverter.canWrite(clazz, mediaType); - } - - @Override - public List getSupportedMediaTypes() { - return this.smartConverter.getSupportedMediaTypes(); - } - - @Override - public T read(Class clazz, HttpInputMessage inputMessage) - throws IOException, HttpMessageNotReadableException { - return this.smartConverter.read(clazz, inputMessage); - } - - @Override - public void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage) - throws IOException, HttpMessageNotWritableException { - this.smartConverter.write(t, contentType, outputMessage); - } - -} diff --git a/webauthn/src/main/java/org/springframework/security/web/webauthn/authentication/WebAuthnAuthenticationFilter.java b/webauthn/src/main/java/org/springframework/security/web/webauthn/authentication/WebAuthnAuthenticationFilter.java index b58ea78b67..c4016a1ef3 100644 --- a/webauthn/src/main/java/org/springframework/security/web/webauthn/authentication/WebAuthnAuthenticationFilter.java +++ b/webauthn/src/main/java/org/springframework/security/web/webauthn/authentication/WebAuthnAuthenticationFilter.java @@ -17,16 +17,25 @@ package org.springframework.security.web.webauthn.authentication; import java.io.IOException; +import java.util.List; +import java.util.Map; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.jspecify.annotations.Nullable; import tools.jackson.databind.json.JsonMapper; import org.springframework.core.ResolvableType; +import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpMethod; +import org.springframework.http.HttpOutputMessage; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.converter.AbstractSmartHttpMessageConverter; import org.springframework.http.converter.GenericHttpMessageConverter; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.http.converter.HttpMessageNotWritableException; import org.springframework.http.converter.SmartHttpMessageConverter; import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter; import org.springframework.http.server.ServletServerHttpRequest; @@ -38,7 +47,6 @@ import org.springframework.security.web.authentication.AuthenticationEntryPointF import org.springframework.security.web.authentication.HttpMessageConverterAuthenticationSuccessHandler; import org.springframework.security.web.authentication.HttpStatusEntryPoint; import org.springframework.security.web.context.HttpSessionSecurityContextRepository; -import org.springframework.security.web.http.GenericHttpMessageConverterAdapter; import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse; import org.springframework.security.web.webauthn.api.PublicKeyCredential; import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions; @@ -74,8 +82,8 @@ import static org.springframework.security.web.servlet.util.matcher.PathPatternR */ public class WebAuthnAuthenticationFilter extends AbstractAuthenticationProcessingFilter { - private GenericHttpMessageConverter converter = new GenericHttpMessageConverterAdapter<>( - new JacksonJsonHttpMessageConverter(JsonMapper.builder().addModule(new WebauthnJacksonModule()).build())); + private SmartHttpMessageConverter converter = new JacksonJsonHttpMessageConverter( + JsonMapper.builder().addModule(new WebauthnJacksonModule()).build()); private PublicKeyCredentialRequestOptionsRepository requestOptionsRepository = new HttpSessionPublicKeyCredentialRequestOptionsRepository(); @@ -96,7 +104,7 @@ public class WebAuthnAuthenticationFilter extends AbstractAuthenticationProcessi PublicKeyCredential publicKeyCredential = null; try { publicKeyCredential = (PublicKeyCredential) this.converter - .read(resolvableType.getType(), getClass(), httpRequest); + .read(resolvableType, httpRequest, null); } catch (Exception ex) { throw new BadCredentialsException("Unable to authenticate the PublicKeyCredential", ex); @@ -118,10 +126,12 @@ public class WebAuthnAuthenticationFilter extends AbstractAuthenticationProcessi * {@code PublicKeyCredential} to the response. The * default is @{code MappingJackson2HttpMessageConverter} * @param converter the {@link GenericHttpMessageConverter} to use. Cannot be null. + * @deprecated use {@link #setConverter(SmartHttpMessageConverter)} */ + @Deprecated(forRemoval = true, since = "7.0") public void setConverter(GenericHttpMessageConverter converter) { Assert.notNull(converter, "converter cannot be null"); - this.converter = converter; + this.converter = new GenericHttpMessageConverterAdapter<>(converter); } /** @@ -133,7 +143,7 @@ public class WebAuthnAuthenticationFilter extends AbstractAuthenticationProcessi */ public void setConverter(SmartHttpMessageConverter converter) { Assert.notNull(converter, "converter cannot be null"); - this.converter = new GenericHttpMessageConverterAdapter<>(converter); + this.converter = converter; } /** @@ -147,4 +157,55 @@ public class WebAuthnAuthenticationFilter extends AbstractAuthenticationProcessi this.requestOptionsRepository = requestOptionsRepository; } + /** + * Adapts a {@link GenericHttpMessageConverter} to a + * {@link SmartHttpMessageConverter}. + * + * @param The type + * @author Rob Winch + * @since 7.0 + */ + private static final class GenericHttpMessageConverterAdapter extends AbstractSmartHttpMessageConverter { + + private final GenericHttpMessageConverter delegate; + + private GenericHttpMessageConverterAdapter(GenericHttpMessageConverter delegate) { + Assert.notNull(delegate, "delegate cannot be null"); + this.delegate = delegate; + } + + @Override + public boolean canRead(Class clazz, @Nullable MediaType mediaType) { + return this.delegate.canRead(clazz, mediaType); + } + + @Override + public boolean canWrite(Class clazz, @Nullable MediaType mediaType) { + return this.delegate.canWrite(clazz, mediaType); + } + + @Override + public List getSupportedMediaTypes() { + return this.delegate.getSupportedMediaTypes(); + } + + @Override + public List getSupportedMediaTypes(Class clazz) { + return this.delegate.getSupportedMediaTypes(clazz); + } + + @Override + protected void writeInternal(T t, ResolvableType type, HttpOutputMessage outputMessage, + @Nullable Map hints) throws IOException, HttpMessageNotWritableException { + this.delegate.write(t, null, outputMessage); + } + + @Override + public T read(ResolvableType type, HttpInputMessage inputMessage, @Nullable Map hints) + throws IOException, HttpMessageNotReadableException { + return this.delegate.read(type.getType(), null, inputMessage); + } + + } + }