diff --git a/core/src/main/java/org/acegisecurity/context/SecurityContext.java b/core/src/main/java/org/acegisecurity/context/SecurityContext.java index a8ef06b1a669..3edc7cb4de9b 100644 --- a/core/src/main/java/org/acegisecurity/context/SecurityContext.java +++ b/core/src/main/java/org/acegisecurity/context/SecurityContext.java @@ -27,46 +27,67 @@ import edu.umd.cs.findbugs.annotations.NonNull; import hudson.model.User; import hudson.security.ACL; +import java.io.Serializable; import org.acegisecurity.Authentication; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; /** * @deprecated Use {@link ACL#as(User)} or {@link org.springframework.security.core.context.SecurityContext} */ @Deprecated -public interface SecurityContext { +public interface SecurityContext extends Serializable { Authentication getAuthentication(); void setAuthentication(Authentication a); static @NonNull SecurityContext fromSpring(@NonNull org.springframework.security.core.context.SecurityContext c) { - return new SecurityContext() { - @Override - public Authentication getAuthentication() { - org.springframework.security.core.Authentication a = c.getAuthentication(); - return a != null ? Authentication.fromSpring(a) : null; - } - - @Override - public void setAuthentication(Authentication a) { - c.setAuthentication(a != null ? a.toSpring() : null); - } - }; + return new FromSpring(c); + } + + @Restricted(NoExternalUse.class) + class FromSpring implements SecurityContext { + private final org.springframework.security.core.context.SecurityContext c; + + FromSpring(org.springframework.security.core.context.SecurityContext c) { + this.c = c; + } + + @Override + public Authentication getAuthentication() { + org.springframework.security.core.Authentication a = c.getAuthentication(); + return a != null ? Authentication.fromSpring(a) : null; + } + + @Override + public void setAuthentication(Authentication a) { + c.setAuthentication(a != null ? a.toSpring() : null); + } } default @NonNull org.springframework.security.core.context.SecurityContext toSpring() { - return new org.springframework.security.core.context.SecurityContext() { - @Override - public org.springframework.security.core.Authentication getAuthentication() { - Authentication a = SecurityContext.this.getAuthentication(); - return a != null ? a.toSpring() : null; - } - - @Override - public void setAuthentication(org.springframework.security.core.Authentication authentication) { - SecurityContext.this.setAuthentication(authentication != null ? Authentication.fromSpring(authentication) : null); - } - }; + return new ToSpring(this); + } + + @Restricted(NoExternalUse.class) + class ToSpring implements org.springframework.security.core.context.SecurityContext { + private final SecurityContext c; + + ToSpring(SecurityContext c) { + this.c = c; + } + + @Override + public org.springframework.security.core.Authentication getAuthentication() { + Authentication a = c.getAuthentication(); + return a != null ? a.toSpring() : null; + } + + @Override + public void setAuthentication(org.springframework.security.core.Authentication authentication) { + c.setAuthentication(authentication != null ? Authentication.fromSpring(authentication) : null); + } } } diff --git a/core/src/test/java/org/acegisecurity/context/SecurityContextTest.java b/core/src/test/java/org/acegisecurity/context/SecurityContextTest.java new file mode 100644 index 000000000000..27539a5cb9ef --- /dev/null +++ b/core/src/test/java/org/acegisecurity/context/SecurityContextTest.java @@ -0,0 +1,69 @@ +/* + * The MIT License + * + * Copyright 2024 CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.acegisecurity.context; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; +import org.junit.jupiter.api.Test; + +@SuppressWarnings("deprecation") +public class SecurityContextTest { + + @Test + public void serializabilityFromSpring() throws Exception { + org.springframework.security.core.context.SecurityContext spring1 = new org.springframework.security.core.context.SecurityContextImpl(); + spring1.setAuthentication(new org.springframework.security.authentication.UsernamePasswordAuthenticationToken("user", null)); + SecurityContext acegi1 = SecurityContext.fromSpring(spring1); + SecurityContext acegi2 = serDeser(SecurityContext.class, acegi1); + org.springframework.security.core.context.SecurityContext spring2 = acegi2.toSpring(); + assertThat(spring2.getAuthentication().getPrincipal(), is("user")); + } + + @Test + public void serializabilityToSpring() throws Exception { + SecurityContext acegi1 = new SecurityContextImpl(); + acegi1.setAuthentication(new UsernamePasswordAuthenticationToken("user", null)); + org.springframework.security.core.context.SecurityContext spring1 = acegi1.toSpring(); + org.springframework.security.core.context.SecurityContext spring2 = serDeser(org.springframework.security.core.context.SecurityContext.class, spring1); + SecurityContext acegi2 = SecurityContext.fromSpring(spring2); + assertThat(acegi2.getAuthentication().getPrincipal(), is("user")); + } + + private static T serDeser(Class type, T object) throws Exception { + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos)) { + oos.writeObject(object); + try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais)) { + return type.cast(ois.readObject()); + } + } + } + +}