Skip to content

Commit 34a9f57

Browse files
committed
Merge branch '6.4.x'
2 parents 74e6bf2 + c3c2bcd commit 34a9f57

11 files changed

+90
-16
lines changed

config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import java.util.Map;
4545
import java.util.Set;
4646
import java.util.UUID;
47+
import java.util.function.Supplier;
4748
import java.util.stream.Stream;
4849

4950
import jakarta.servlet.http.Cookie;
@@ -68,6 +69,7 @@
6869
import org.springframework.security.access.AccessDeniedException;
6970
import org.springframework.security.access.AuthorizationServiceException;
7071
import org.springframework.security.access.SecurityConfig;
72+
import org.springframework.security.access.hierarchicalroles.CycleInRoleHierarchyException;
7173
import org.springframework.security.access.intercept.RunAsUserToken;
7274
import org.springframework.security.authentication.AbstractAuthenticationToken;
7375
import org.springframework.security.authentication.AccountExpiredException;
@@ -106,9 +108,12 @@
106108
import org.springframework.security.authorization.AuthorityAuthorizationDecision;
107109
import org.springframework.security.authorization.AuthorizationDecision;
108110
import org.springframework.security.authorization.AuthorizationDeniedException;
111+
import org.springframework.security.authorization.event.AuthorizationEvent;
112+
import org.springframework.security.authorization.event.AuthorizationGrantedEvent;
109113
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
110114
import org.springframework.security.cas.authentication.CasAuthenticationToken;
111115
import org.springframework.security.cas.authentication.CasServiceTicketAuthenticationToken;
116+
import org.springframework.security.config.annotation.AlreadyBuiltException;
112117
import org.springframework.security.core.Authentication;
113118
import org.springframework.security.core.GrantedAuthority;
114119
import org.springframework.security.core.SpringSecurityCoreVersion;
@@ -195,8 +200,10 @@
195200
import org.springframework.security.saml2.provider.service.authentication.Saml2RedirectAuthenticationRequest;
196201
import org.springframework.security.saml2.provider.service.authentication.TestSaml2AuthenticationTokens;
197202
import org.springframework.security.saml2.provider.service.authentication.TestSaml2Authentications;
203+
import org.springframework.security.saml2.provider.service.authentication.TestSaml2LogoutRequests;
198204
import org.springframework.security.saml2.provider.service.authentication.TestSaml2PostAuthenticationRequests;
199205
import org.springframework.security.saml2.provider.service.authentication.TestSaml2RedirectAuthenticationRequests;
206+
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
200207
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
201208
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.AssertingPartyDetails;
202209
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
@@ -220,6 +227,7 @@
220227
import org.springframework.security.web.savedrequest.SimpleSavedRequest;
221228
import org.springframework.security.web.server.firewall.ServerExchangeRejectedException;
222229
import org.springframework.security.web.session.HttpSessionCreatedEvent;
230+
import org.springframework.security.web.session.HttpSessionIdChangedEvent;
223231
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs;
224232
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs;
225233
import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
@@ -269,6 +277,8 @@ class SpringSecurityCoreVersionSerializableTests {
269277

270278
private static final Map<Class<?>, Generator<?>> generatorByClassName = new HashMap<>();
271279

280+
private static final Map<Class<?>, Supplier<InstancioApi<?>>> instancioByClassName = new HashMap<>();
281+
272282
static final long securitySerialVersionUid = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
273283

274284
static Path currentVersionFolder = Paths.get("src/test/resources/serialized/" + getCurrentVersion());
@@ -402,6 +412,9 @@ class SpringSecurityCoreVersionSerializableTests {
402412
generatorByClassName.put(OAuth2IntrospectionException.class,
403413
(r) -> new OAuth2IntrospectionException("message", new RuntimeException()));
404414

415+
// config
416+
generatorByClassName.put(AlreadyBuiltException.class, (r) -> new AlreadyBuiltException("message"));
417+
405418
// core
406419
generatorByClassName.put(RunAsUserToken.class, (r) -> {
407420
RunAsUserToken token = new RunAsUserToken("key", user, "creds", user.getAuthorities(),
@@ -493,6 +506,20 @@ class SpringSecurityCoreVersionSerializableTests {
493506
generatorByClassName.put(AuthorizationDecision.class, (r) -> new AuthorizationDecision(true));
494507
generatorByClassName.put(AuthorityAuthorizationDecision.class,
495508
(r) -> new AuthorityAuthorizationDecision(true, AuthorityUtils.createAuthorityList("ROLE_USER")));
509+
generatorByClassName.put(CycleInRoleHierarchyException.class, (r) -> new CycleInRoleHierarchyException());
510+
generatorByClassName.put(AuthorizationEvent.class,
511+
(r) -> new AuthorizationEvent(new SerializableSupplier<>(authentication), "source",
512+
new AuthorizationDecision(true)));
513+
generatorByClassName.put(AuthorizationGrantedEvent.class,
514+
(r) -> new AuthorizationGrantedEvent<>(new SerializableSupplier<>(authentication), "source",
515+
new AuthorizationDecision(true)));
516+
instancioByClassName.put(AuthorizationGrantedEvent.class, () -> {
517+
InstancioOfClassApi<?> instancio = Instancio.of(AuthorizationGrantedEvent.class);
518+
instancio.withTypeParameters(String.class);
519+
instancio.supply(Select.all(AuthorizationGrantedEvent.class),
520+
generatorByClassName.get(AuthorizationGrantedEvent.class));
521+
return instancio;
522+
});
496523

497524
// cas
498525
generatorByClassName.put(CasServiceTicketAuthenticationToken.class, (r) -> {
@@ -546,6 +573,7 @@ class SpringSecurityCoreVersionSerializableTests {
546573
token.setDetails(details);
547574
return token;
548575
});
576+
generatorByClassName.put(Saml2LogoutRequest.class, (r) -> TestSaml2LogoutRequests.create());
549577

550578
// web
551579
generatorByClassName.put(AnonymousAuthenticationToken.class, (r) -> {
@@ -602,6 +630,9 @@ class SpringSecurityCoreVersionSerializableTests {
602630
return new SimpleSavedRequest(new DefaultSavedRequest(request, new PortResolverImpl(), "continue"));
603631
});
604632

633+
generatorByClassName.put(HttpSessionIdChangedEvent.class,
634+
(r) -> new HttpSessionIdChangedEvent(new MockHttpSession(), "1"));
635+
605636
// webauthn
606637
CredProtectAuthenticationExtensionsClientInput.CredProtect credProtect = new CredProtectAuthenticationExtensionsClientInput.CredProtect(
607638
CredProtectAuthenticationExtensionsClientInput.CredProtect.ProtectionPolicy.USER_VERIFICATION_OPTIONAL,
@@ -670,6 +701,9 @@ class SpringSecurityCoreVersionSerializableTests {
670701
});
671702
// @formatter:on
672703

704+
generatorByClassName.put(CredentialPropertiesOutput.ExtensionOutput.class,
705+
(r) -> new CredentialPropertiesOutput(true).getOutput());
706+
673707
// One-Time Token
674708
DefaultOneTimeToken oneTimeToken = new DefaultOneTimeToken(UUID.randomUUID().toString(), "user",
675709
Instant.now().plusSeconds(300));
@@ -742,7 +776,28 @@ void serializeCurrentVersionClasses(Class<?> clazz) throws Exception {
742776
}
743777

744778
@ParameterizedTest
745-
@MethodSource("getFilesToDeserialize")
779+
@MethodSource("getCurrentSerializedFiles")
780+
void shouldBeAbleToDeserializeClassFromCurrentVersion(Path filePath) {
781+
try (FileInputStream fileInputStream = new FileInputStream(filePath.toFile());
782+
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) {
783+
Object obj = objectInputStream.readObject();
784+
Class<?> clazz = Class.forName(filePath.getFileName().toString().replace(".serialized", ""));
785+
assertThat(obj).isInstanceOf(clazz);
786+
}
787+
catch (IOException | ClassNotFoundException ex) {
788+
fail("Could not deserialize " + filePath, ex);
789+
}
790+
}
791+
792+
static Stream<Path> getCurrentSerializedFiles() throws Exception {
793+
assertThat(currentVersionFolder.toFile().exists())
794+
.as("Make sure that the " + currentVersionFolder + " exists and is not empty")
795+
.isTrue();
796+
return getClassesToSerialize().map((clazz) -> currentVersionFolder.resolve(clazz.getName() + ".serialized"));
797+
}
798+
799+
@ParameterizedTest
800+
@MethodSource("getPreviousSerializedFiles")
746801
void shouldBeAbleToDeserializeClassFromPreviousVersion(Path filePath) {
747802
try (FileInputStream fileInputStream = new FileInputStream(filePath.toFile());
748803
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) {
@@ -755,7 +810,7 @@ void shouldBeAbleToDeserializeClassFromPreviousVersion(Path filePath) {
755810
}
756811
}
757812

758-
static Stream<Path> getFilesToDeserialize() throws IOException {
813+
static Stream<Path> getPreviousSerializedFiles() throws IOException {
759814
assertThat(previousVersionFolder.toFile().exists())
760815
.as("Make sure that the " + previousVersionFolder + " exists and is not empty")
761816
.isTrue();
@@ -791,10 +846,18 @@ void allSerializableClassesShouldHaveSerialVersionOrSuppressWarnings() throws Ex
791846
|| Arrays.asList(suppressWarnings.value()).contains("Serial");
792847
if (!hasSerialVersion && !hasSerialIgnore) {
793848
classes.add(clazz);
849+
continue;
850+
}
851+
boolean isReachable = Modifier.isPublic(clazz.getModifiers());
852+
boolean hasSampleSerialization = currentVersionFolder.resolve(clazz.getName() + ".serialized")
853+
.toFile()
854+
.exists();
855+
if (hasSerialVersion && isReachable && !hasSampleSerialization) {
856+
classes.add(clazz);
794857
}
795858
}
796-
assertThat(classes)
797-
.describedAs("Found Serializable classes that are either missing a serialVersionUID or a @SuppressWarnings")
859+
assertThat(classes).describedAs(
860+
"Found Serializable classes that are either missing a serialVersionUID or a @SuppressWarnings or a sample serialized file")
798861
.isEmpty();
799862
}
800863

@@ -821,6 +884,9 @@ static Stream<Class<?>> getClassesToSerialize() throws Exception {
821884
}
822885

823886
private static InstancioApi<?> instancioWithDefaults(Class<?> clazz) {
887+
if (instancioByClassName.containsKey(clazz)) {
888+
return instancioByClassName.get(clazz).get();
889+
}
824890
InstancioOfClassApi<?> instancio = Instancio.of(clazz);
825891
ResolvableType[] generics = ResolvableType.forClass(clazz).getGenerics();
826892
for (ResolvableType type : generics) {
@@ -853,4 +919,20 @@ private static String getPreviousVersion() {
853919
return String.join(".", parts);
854920
}
855921

922+
@SuppressWarnings("serial")
923+
private static final class SerializableSupplier<T> implements Supplier<T>, Serializable {
924+
925+
private final T value;
926+
927+
SerializableSupplier(T value) {
928+
this.value = value;
929+
}
930+
931+
@Override
932+
public T get() {
933+
return this.value;
934+
}
935+
936+
}
937+
856938
}

config/src/test/java/org/springframework/security/config/annotation/method/configuration/Authz.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public Mono<AuthorizationResult> checkReactiveResult(boolean result) {
5555
return Mono.just(checkResult(result));
5656
}
5757

58+
@SuppressWarnings("serial")
5859
public static class AuthzResult extends AuthorizationDecision {
5960

6061
public AuthzResult(boolean granted) {

core/src/test/java/org/springframework/security/access/annotation/BusinessServiceImpl.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,15 @@
1616

1717
package org.springframework.security.access.annotation;
1818

19-
import java.io.Serial;
2019
import java.util.ArrayList;
2120
import java.util.List;
2221

2322
/**
2423
* @author Joe Scalise
2524
*/
25+
@SuppressWarnings("serial")
2626
public class BusinessServiceImpl<E extends Entity> implements BusinessService {
2727

28-
@Serial
29-
private static final long serialVersionUID = -4249394090237180795L;
30-
3128
@Override
3229
@Secured({ "ROLE_USER" })
3330
public void someUserMethod1() {

core/src/test/java/org/springframework/security/access/annotation/ExpressionProtectedBusinessServiceImpl.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,16 @@
1616

1717
package org.springframework.security.access.annotation;
1818

19-
import java.io.Serial;
2019
import java.util.ArrayList;
2120
import java.util.List;
2221

2322
import org.springframework.security.access.prepost.PostFilter;
2423
import org.springframework.security.access.prepost.PreAuthorize;
2524
import org.springframework.security.access.prepost.PreFilter;
2625

26+
@SuppressWarnings("serial")
2727
public class ExpressionProtectedBusinessServiceImpl implements BusinessService {
2828

29-
@Serial
30-
private static final long serialVersionUID = -3320014879907436606L;
31-
3229
@Override
3330
public void someAdminMethod() {
3431
}

0 commit comments

Comments
 (0)