diff --git a/web/src/main/java/org/springframework/security/web/method/annotation/CurrentSecurityContextArgumentResolver.java b/web/src/main/java/org/springframework/security/web/method/annotation/CurrentSecurityContextArgumentResolver.java index 6cbdb0c2d2..304d16e824 100644 --- a/web/src/main/java/org/springframework/security/web/method/annotation/CurrentSecurityContextArgumentResolver.java +++ b/web/src/main/java/org/springframework/security/web/method/annotation/CurrentSecurityContextArgumentResolver.java @@ -98,6 +98,7 @@ public final class CurrentSecurityContextArgumentResolver implements HandlerMeth StandardEvaluationContext context = new StandardEvaluationContext(); context.setRootObject(securityContext); context.setVariable("this", securityContext); + context.setBeanResolver(this.beanResolver); Expression expression = this.parser.parseExpression(expressionToParse); securityContextResult = expression.getValue(context); } diff --git a/web/src/test/java/org/springframework/security/web/method/annotation/AuthenticationPrincipalArgumentResolverTests.java b/web/src/test/java/org/springframework/security/web/method/annotation/AuthenticationPrincipalArgumentResolverTests.java index dfd3d504ca..71b55dad6e 100644 --- a/web/src/test/java/org/springframework/security/web/method/annotation/AuthenticationPrincipalArgumentResolverTests.java +++ b/web/src/test/java/org/springframework/security/web/method/annotation/AuthenticationPrincipalArgumentResolverTests.java @@ -21,12 +21,15 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; +import java.util.function.Function; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.core.MethodParameter; +import org.springframework.expression.AccessException; +import org.springframework.expression.BeanResolver; import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.authority.AuthorityUtils; @@ -44,6 +47,13 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; */ public class AuthenticationPrincipalArgumentResolverTests { + private final BeanResolver beanResolver = ((context, beanName) -> { + if (!"test".equals(beanName)) { + throw new AccessException("Could not resolve bean reference against BeanFactory"); + } + return (Function) (principal) -> principal.property; + }); + private Object expectedPrincipal; private AuthenticationPrincipalArgumentResolver resolver; @@ -51,6 +61,7 @@ public class AuthenticationPrincipalArgumentResolverTests { @Before public void setup() { this.resolver = new AuthenticationPrincipalArgumentResolver(); + this.resolver.setBeanResolver(this.beanResolver); } @After @@ -127,6 +138,14 @@ public class AuthenticationPrincipalArgumentResolverTests { assertThat(this.resolver.resolveArgument(showUserSpel(), null, null, null)).isEqualTo(this.expectedPrincipal); } + @Test + public void resolveArgumentSpelBean() throws Exception { + CustomUserPrincipal principal = new CustomUserPrincipal(); + setAuthenticationPrincipal(principal); + this.expectedPrincipal = principal.property; + assertThat(this.resolver.resolveArgument(showUserSpelBean(), null, null, null)).isEqualTo(this.expectedPrincipal); + } + @Test public void resolveArgumentSpelCopy() throws Exception { CopyUserPrincipal principal = new CopyUserPrincipal("property"); @@ -195,6 +214,10 @@ public class AuthenticationPrincipalArgumentResolverTests { return getMethodParameter("showUserSpel", String.class); } + private MethodParameter showUserSpelBean() { + return getMethodParameter("showUserSpelBean", String.class); + } + private MethodParameter showUserSpelCopy() { return getMethodParameter("showUserSpelCopy", CopyUserPrincipal.class); } @@ -258,6 +281,10 @@ public class AuthenticationPrincipalArgumentResolverTests { public void showUserSpel(@AuthenticationPrincipal(expression = "property") String user) { } + public void showUserSpelBean(@AuthenticationPrincipal( + expression = "@test.apply(#this)") String user) { + } + public void showUserSpelCopy(@AuthenticationPrincipal( expression = "new org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolverTests$CopyUserPrincipal(#this)") CopyUserPrincipal user) { } diff --git a/web/src/test/java/org/springframework/security/web/method/annotation/CurrentSecurityContextArgumentResolverTests.java b/web/src/test/java/org/springframework/security/web/method/annotation/CurrentSecurityContextArgumentResolverTests.java index 71d6687f9d..5da25d719c 100644 --- a/web/src/test/java/org/springframework/security/web/method/annotation/CurrentSecurityContextArgumentResolverTests.java +++ b/web/src/test/java/org/springframework/security/web/method/annotation/CurrentSecurityContextArgumentResolverTests.java @@ -21,12 +21,15 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; +import java.util.function.Function; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.core.MethodParameter; +import org.springframework.expression.AccessException; +import org.springframework.expression.BeanResolver; import org.springframework.expression.spel.SpelEvaluationException; import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.core.Authentication; @@ -47,11 +50,19 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; */ public class CurrentSecurityContextArgumentResolverTests { + private final BeanResolver beanResolver = ((context, beanName) -> { + if (!"test".equals(beanName)) { + throw new AccessException("Could not resolve bean reference against BeanFactory"); + } + return (Function) SecurityContext::getAuthentication; + }); + private CurrentSecurityContextArgumentResolver resolver; @Before public void setup() { this.resolver = new CurrentSecurityContextArgumentResolver(); + this.resolver.setBeanResolver(this.beanResolver); } @After @@ -106,6 +117,15 @@ public class CurrentSecurityContextArgumentResolverTests { assertThat(auth1.getPrincipal()).isEqualTo(principal); } + @Test + public void resolveArgumentWithAuthenticationWithBean() { + String principal = "john"; + setAuthenticationPrincipal(principal); + Authentication auth1 = (Authentication) this.resolver + .resolveArgument(showSecurityContextAuthenticationWithBean(), null, null, null); + assertThat(auth1.getPrincipal()).isEqualTo(principal); + } + @Test public void resolveArgumentWithNullAuthentication() { SecurityContext context = SecurityContextHolder.getContext(); @@ -213,6 +233,10 @@ public class CurrentSecurityContextArgumentResolverTests { return getMethodParameter("showSecurityContextAuthenticationAnnotation", Authentication.class); } + public MethodParameter showSecurityContextAuthenticationWithBean() { + return getMethodParameter("showSecurityContextAuthenticationWithBean", Authentication.class); + } + private MethodParameter showSecurityContextAuthenticationWithOptionalPrincipal() { return getMethodParameter("showSecurityContextAuthenticationWithOptionalPrincipal", Object.class); } @@ -294,6 +318,10 @@ public class CurrentSecurityContextArgumentResolverTests { @CurrentSecurityContext(expression = "authentication") Authentication authentication) { } + public void showSecurityContextAuthenticationWithBean( + @CurrentSecurityContext(expression = "@test.apply(#this)") Authentication authentication) { + } + public void showSecurityContextAuthenticationWithOptionalPrincipal( @CurrentSecurityContext(expression = "authentication?.principal") Object principal) { }