DefaultWebSecurityExpressionHandler uses PermissionEvaluator Bean

The default instance of DefaultWebSecurityExpressionHandler uses the
PermissionEvaluator Bean by default.

Fixes: gh-5272
This commit is contained in:
Rob Winch 2018-04-30 11:41:43 -05:00
parent 0b72f93027
commit f7f6798f71
2 changed files with 64 additions and 12 deletions

View File

@ -29,6 +29,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.expression.SecurityExpressionHandler; import org.springframework.security.access.expression.SecurityExpressionHandler;
import org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder; import org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder;
import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.ObjectPostProcessor;
@ -382,6 +383,11 @@ public final class WebSecurity extends
throws BeansException { throws BeansException {
this.defaultWebSecurityExpressionHandler this.defaultWebSecurityExpressionHandler
.setApplicationContext(applicationContext); .setApplicationContext(applicationContext);
try {
this.defaultWebSecurityExpressionHandler.setPermissionEvaluator(applicationContext.getBean(
PermissionEvaluator.class));
} catch(NoSuchBeanDefinitionException e) {}
this.ignoredRequestRegistry = new IgnoredRequestConfigurer(applicationContext); this.ignoredRequestRegistry = new IgnoredRequestConfigurer(applicationContext);
try { try {
this.httpFirewall = applicationContext.getBean(HttpFirewall.class); this.httpFirewall = applicationContext.getBean(HttpFirewall.class);

View File

@ -15,6 +15,19 @@
*/ */
package org.springframework.security.config.annotation.web.configuration; package org.springframework.security.config.annotation.web.configuration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCreationException;
@ -23,15 +36,24 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser; import org.springframework.expression.ExpressionParser;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
import org.springframework.security.access.expression.SecurityExpressionHandler; import org.springframework.security.access.expression.SecurityExpressionHandler;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.test.SpringTestRule; import org.springframework.security.config.test.SpringTestRule;
import org.springframework.security.config.users.AuthenticationTestConfiguration; import org.springframework.security.config.users.AuthenticationTestConfiguration;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator;
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
@ -41,18 +63,6 @@ import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/** /**
* Tests for {@link WebSecurityConfiguration}. * Tests for {@link WebSecurityConfiguration}.
* *
@ -260,6 +270,42 @@ public class WebSecurityConfigurationTests {
} }
} }
@Test
public void securityExpressionHandlerWhenPermissionEvaluatorBeanThenPermissionEvaluatorUsed() throws Exception {
this.spring.register(WebSecurityExpressionHandlerPermissionEvaluatorBeanConfig.class).autowire();
TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "notused");
FilterInvocation invocation = new FilterInvocation(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain());
AbstractSecurityExpressionHandler handler = this.spring.getContext().getBean(AbstractSecurityExpressionHandler.class);
EvaluationContext evaluationContext = handler.createEvaluationContext(authentication, invocation);
Expression expression = handler.getExpressionParser()
.parseExpression("hasPermission(#study,'DELETE')");
boolean granted = expression.getValue(evaluationContext, Boolean.class);
assertThat(granted).isTrue();
}
@EnableWebSecurity
static class WebSecurityExpressionHandlerPermissionEvaluatorBeanConfig extends WebSecurityConfigurerAdapter {
static final PermissionEvaluator PERMIT_ALL_PERMISSION_EVALUATOR = new PermissionEvaluator() {
@Override
public boolean hasPermission(Authentication authentication,
Object targetDomainObject, Object permission) {
return true;
}
@Override
public boolean hasPermission(Authentication authentication,
Serializable targetId, String targetType, Object permission) {
return true;
}
};
@Bean
public PermissionEvaluator permissionEvaluator() {
return PERMIT_ALL_PERMISSION_EVALUATOR;
}
}
@Test @Test
public void loadConfigWhenDefaultWebInvocationPrivilegeEvaluatorThenDefaultIsRegistered() throws Exception { public void loadConfigWhenDefaultWebInvocationPrivilegeEvaluatorThenDefaultIsRegistered() throws Exception {
this.spring.register(WebInvocationPrivilegeEvaluatorDefaultsConfig.class).autowire(); this.spring.register(WebInvocationPrivilegeEvaluatorDefaultsConfig.class).autowire();