createEvaluationContext should defer lookup of Authentication
- Added createEvaluationContext method that accepts Supplier<Authentication> - Refactored classes that use EvaluationContext to use lazy initialization of Authentication Closes gh-9667
This commit is contained in:
committed by
Josh Cummings
parent
7d97839235
commit
362f15534e
+19
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
package org.springframework.security.messaging.access.expression;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
||||
@@ -31,15 +35,29 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @param <T> the type for the body of the Message
|
||||
* @author Rob Winch
|
||||
* @author Evgeniy Cheban
|
||||
* @since 4.0
|
||||
*/
|
||||
public class DefaultMessageSecurityExpressionHandler<T> extends AbstractSecurityExpressionHandler<Message<T>> {
|
||||
|
||||
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||
|
||||
@Override
|
||||
public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication, Message<T> message) {
|
||||
MessageSecurityExpressionRoot root = createSecurityExpressionRoot(authentication, message);
|
||||
StandardEvaluationContext ctx = new StandardEvaluationContext(root);
|
||||
ctx.setBeanResolver(getBeanResolver());
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
|
||||
Message<T> invocation) {
|
||||
return createSecurityExpressionRoot(() -> authentication, invocation);
|
||||
}
|
||||
|
||||
private MessageSecurityExpressionRoot createSecurityExpressionRoot(Supplier<Authentication> authentication,
|
||||
Message<T> invocation) {
|
||||
MessageSecurityExpressionRoot root = new MessageSecurityExpressionRoot(authentication, invocation);
|
||||
root.setPermissionEvaluator(getPermissionEvaluator());
|
||||
root.setTrustResolver(this.trustResolver);
|
||||
|
||||
+15
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.security.messaging.access.expression;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.security.access.expression.SecurityExpressionRoot;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -24,6 +26,7 @@ import org.springframework.security.core.Authentication;
|
||||
* The {@link SecurityExpressionRoot} used for {@link Message} expressions.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Evgeniy Cheban
|
||||
* @since 4.0
|
||||
*/
|
||||
public class MessageSecurityExpressionRoot extends SecurityExpressionRoot {
|
||||
@@ -31,6 +34,17 @@ public class MessageSecurityExpressionRoot extends SecurityExpressionRoot {
|
||||
public final Message<?> message;
|
||||
|
||||
public MessageSecurityExpressionRoot(Authentication authentication, Message<?> message) {
|
||||
this(() -> authentication, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance for the given {@link Supplier} of the {@link Authentication}
|
||||
* and {@link Message}.
|
||||
* @param authentication the {@link Supplier} of the {@link Authentication} to use
|
||||
* @param message the {@link Message} to use
|
||||
* @since 5.8
|
||||
*/
|
||||
public MessageSecurityExpressionRoot(Supplier<Authentication> authentication, Message<?> message) {
|
||||
super(authentication);
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
+21
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.security.messaging.access.expression;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -24,10 +27,12 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.TypedValue;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.access.expression.ExpressionUtils;
|
||||
import org.springframework.security.access.expression.SecurityExpressionRoot;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
@@ -38,6 +43,9 @@ import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class DefaultMessageSecurityExpressionHandlerTests {
|
||||
@@ -104,4 +112,16 @@ public class DefaultMessageSecurityExpressionHandlerTests {
|
||||
assertThat(ExpressionUtils.evaluateAsBoolean(expression, context)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createEvaluationContextSupplierAuthentication() {
|
||||
Supplier<Authentication> mockAuthenticationSupplier = mock(Supplier.class);
|
||||
given(mockAuthenticationSupplier.get()).willReturn(this.authentication);
|
||||
EvaluationContext context = this.handler.createEvaluationContext(mockAuthenticationSupplier, this.message);
|
||||
verifyNoInteractions(mockAuthenticationSupplier);
|
||||
assertThat(context.getRootObject()).extracting(TypedValue::getValue)
|
||||
.asInstanceOf(InstanceOfAssertFactories.type(MessageSecurityExpressionRoot.class))
|
||||
.extracting(SecurityExpressionRoot::getAuthentication).isEqualTo(this.authentication);
|
||||
verify(mockAuthenticationSupplier).get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user