diff --git a/build.gradle b/build.gradle index 1caa0915a3..79daa62fb7 100644 --- a/build.gradle +++ b/build.gradle @@ -110,7 +110,6 @@ subprojects { tasks.withType(JavaCompile) { options.encoding = "UTF-8" options.compilerArgs.add("-parameters") - options.release = 8 } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java index 0f26791597..ca7ef5720d 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java @@ -18,7 +18,6 @@ package org.springframework.security.config.annotation.web.configurers.oauth2.se import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Supplier; @@ -28,7 +27,6 @@ import javax.servlet.http.HttpServletRequest; import org.springframework.context.ApplicationContext; import org.springframework.core.convert.converter.Converter; import org.springframework.http.MediaType; -import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManagerResolver; @@ -161,18 +159,13 @@ public final class OAuth2ResourceServerConfigurer(createAccessDeniedHandlers()), new BearerTokenAccessDeniedHandler()); + new LinkedHashMap<>(Map.of(CsrfException.class, new AccessDeniedHandlerImpl())), + new BearerTokenAccessDeniedHandler()); private AuthenticationEntryPoint authenticationEntryPoint = new BearerTokenAuthenticationEntryPoint(); private BearerTokenRequestMatcher requestMatcher = new BearerTokenRequestMatcher(); - private static Map, AccessDeniedHandler> createAccessDeniedHandlers() { - Map, AccessDeniedHandler> handlers = new HashMap<>(); - handlers.put(CsrfException.class, new AccessDeniedHandlerImpl()); - return handlers; - } - public OAuth2ResourceServerConfigurer(ApplicationContext context) { Assert.notNull(context, "context cannot be null"); this.context = context; diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java index ee8e598ff1..eb56460ecd 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java @@ -359,7 +359,8 @@ public final class Saml2LoginConfigurer> if (version != null) { return version; } - return Version.getVersion(); + return Version.class.getModule().getDescriptor().version().map(Object::toString) + .orElseThrow(() -> new IllegalStateException("cannot determine OpenSAML version")); } private void registerDefaultAuthenticationProvider(B http) { diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LogoutConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LogoutConfigurer.java index 9e4c4eac0f..45bd549c01 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LogoutConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LogoutConfigurer.java @@ -319,7 +319,8 @@ public final class Saml2LogoutConfigurer> if (version != null) { return version; } - return Version.getVersion(); + return Version.class.getModule().getDescriptor().version().map(Object::toString) + .orElseThrow(() -> new IllegalStateException("cannot determine OpenSAML version")); } /** diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java index 7868021f15..d54a0a286e 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java @@ -21,13 +21,11 @@ import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; -import javax.security.auth.x500.X500Principal; import javax.servlet.http.HttpServletRequest; -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x500.style.BCStyle; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import sun.security.x509.X500Name; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; @@ -242,8 +240,12 @@ public class NamespaceHttpX509Tests { } private String extractCommonName(X509Certificate certificate) { - X500Principal principal = certificate.getSubjectX500Principal(); - return new X500Name(principal.getName()).getRDNs(BCStyle.CN)[0].getFirst().getValue().toString(); + try { + return ((X500Name) certificate.getSubjectDN()).getCommonName(); + } + catch (Exception ex) { + throw new IllegalArgumentException(ex); + } } } diff --git a/core/src/test/java/org/springframework/security/core/SpringSecurityCoreVersionTests.java b/core/src/test/java/org/springframework/security/core/SpringSecurityCoreVersionTests.java index d2d9b0e665..fe2bfbadb1 100644 --- a/core/src/test/java/org/springframework/security/core/SpringSecurityCoreVersionTests.java +++ b/core/src/test/java/org/springframework/security/core/SpringSecurityCoreVersionTests.java @@ -18,7 +18,6 @@ package org.springframework.security.core; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -61,24 +60,15 @@ public class SpringSecurityCoreVersionTests { @BeforeEach public void setup() throws Exception { - setFinalStaticField(SpringSecurityCoreVersion.class, "logger", this.logger); + Field logger = ReflectionUtils.findField(SpringSecurityCoreVersion.class, "logger"); + StaticFinalReflectionUtils.setField(logger, this.logger); } @AfterEach public void cleanup() throws Exception { System.clearProperty(getDisableChecksProperty()); - setFinalStaticField(SpringSecurityCoreVersion.class, "logger", - LogFactory.getLog(SpringSecurityCoreVersion.class)); - } - - private static void setFinalStaticField(Class clazz, String fieldName, Object value) - throws ReflectiveOperationException { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - Field modifiers = Field.class.getDeclaredField("modifiers"); - modifiers.setAccessible(true); - modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); - field.set(null, value); + Field logger = ReflectionUtils.findField(SpringSecurityCoreVersion.class, "logger"); + StaticFinalReflectionUtils.setField(logger, LogFactory.getLog(SpringSecurityCoreVersion.class)); } @Test diff --git a/core/src/test/java/org/springframework/security/core/StaticFinalReflectionUtils.java b/core/src/test/java/org/springframework/security/core/StaticFinalReflectionUtils.java new file mode 100644 index 0000000000..1cff222680 --- /dev/null +++ b/core/src/test/java/org/springframework/security/core/StaticFinalReflectionUtils.java @@ -0,0 +1,115 @@ +/* + * Copyright 2008 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.core; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import sun.misc.Unsafe; + +import org.springframework.objenesis.instantiator.util.UnsafeUtils; + +/** + * Used for setting static variables even if they are private static final. + * + * The code in this class has been adopted from Powermock's WhiteboxImpl. + * + * @author Rob Winch + */ +final class StaticFinalReflectionUtils { + + /** + * Used to support setting static fields that are final using Java's Unsafe. If the + * field is not static final, use + * {@link org.springframework.test.util.ReflectionTestUtils}. + * @param field the field to set + * @param newValue the new value + */ + static void setField(final Field field, final Object newValue) { + try { + field.setAccessible(true); + int fieldModifiersMask = field.getModifiers(); + boolean isFinalModifierPresent = (fieldModifiersMask & Modifier.FINAL) == Modifier.FINAL; + if (isFinalModifierPresent) { + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Object run() { + try { + Unsafe unsafe = UnsafeUtils.getUnsafe(); + long offset = unsafe.staticFieldOffset(field); + Object base = unsafe.staticFieldBase(field); + setFieldUsingUnsafe(base, field.getType(), offset, newValue, unsafe); + return null; + } + catch (Throwable thrown) { + throw new RuntimeException(thrown); + } + } + }); + } + else { + field.set(null, newValue); + } + } + catch (SecurityException ex) { + throw new RuntimeException(ex); + } + catch (IllegalAccessException ex) { + throw new RuntimeException(ex); + } + catch (IllegalArgumentException ex) { + throw new RuntimeException(ex); + } + } + + private static void setFieldUsingUnsafe(Object base, Class type, long offset, Object newValue, Unsafe unsafe) { + if (type == Integer.TYPE) { + unsafe.putInt(base, offset, ((Integer) newValue)); + } + else if (type == Short.TYPE) { + unsafe.putShort(base, offset, ((Short) newValue)); + } + else if (type == Long.TYPE) { + unsafe.putLong(base, offset, ((Long) newValue)); + } + else if (type == Byte.TYPE) { + unsafe.putByte(base, offset, ((Byte) newValue)); + } + else if (type == Boolean.TYPE) { + unsafe.putBoolean(base, offset, ((Boolean) newValue)); + } + else if (type == Float.TYPE) { + unsafe.putFloat(base, offset, ((Float) newValue)); + } + else if (type == Double.TYPE) { + unsafe.putDouble(base, offset, ((Double) newValue)); + } + else if (type == Character.TYPE) { + unsafe.putChar(base, offset, ((Character) newValue)); + } + else { + unsafe.putObject(base, offset, newValue); + } + } + + private StaticFinalReflectionUtils() { + } + +}