1
0
mirror of synced 2026-08-02 16:27:08 +00:00

Make single definition of defaultRolePrefix and rolePrefix

Previous to this commit, role prefix had to be set in every class
causing repetition. Now, bean `GrantedAuthorityDefaults` can be used to
define the role prefix in a single point.

Fixes gh-3701
This commit is contained in:
Eddú Meléndez
2016-06-21 16:55:16 +10:00
committed by Rob Winch
parent 2e6656e9d3
commit eabeaf35d6
13 changed files with 362 additions and 29 deletions
@@ -15,11 +15,14 @@
*/
package org.springframework.security.web.access.expression;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
import org.springframework.security.access.expression.SecurityExpressionHandler;
import org.springframework.security.access.expression.SecurityExpressionOperations;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.config.GrantedAuthorityDefaults;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.FilterInvocation;
import org.springframework.util.Assert;
@@ -27,6 +30,7 @@ import org.springframework.util.Assert;
/**
*
* @author Luke Taylor
* @author Eddú Meléndez
* @since 3.0
*/
public class DefaultWebSecurityExpressionHandler extends
@@ -34,7 +38,7 @@ public class DefaultWebSecurityExpressionHandler extends
SecurityExpressionHandler<FilterInvocation> {
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
private String defaultRolePrefix = "ROLE_";
private GrantedAuthorityDefaults defaultRolePrefix = new GrantedAuthorityDefaults("ROLE_");
@Override
protected SecurityExpressionOperations createSecurityExpressionRoot(
@@ -43,7 +47,7 @@ public class DefaultWebSecurityExpressionHandler extends
root.setPermissionEvaluator(getPermissionEvaluator());
root.setTrustResolver(trustResolver);
root.setRoleHierarchy(getRoleHierarchy());
root.setDefaultRolePrefix(defaultRolePrefix);
root.setDefaultRolePrefix(this.defaultRolePrefix.getRolePrefix());
return root;
}
@@ -74,6 +78,16 @@ public class DefaultWebSecurityExpressionHandler extends
* @param defaultRolePrefix the default prefix to add to roles. Default "ROLE_".
*/
public void setDefaultRolePrefix(String defaultRolePrefix) {
this.defaultRolePrefix = defaultRolePrefix;
this.defaultRolePrefix = new GrantedAuthorityDefaults(defaultRolePrefix);
}
@Override
public void setApplicationContext(ApplicationContext context) {
super.setApplicationContext(context);
String[] beanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class);
if (beanNames.length == 1) {
this.defaultRolePrefix = context.getBean(beanNames[0], GrantedAuthorityDefaults.class);
}
}
}
@@ -27,9 +27,13 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.config.GrantedAuthorityDefaults;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.AuthenticationEntryPoint;
@@ -71,12 +75,13 @@ import org.springframework.web.filter.GenericFilterBean;
* @author Ben Alex
* @author Luke Taylor
* @author Rob Winch
* @author Eddú Meléndez
*/
public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {
public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean implements ApplicationContextAware {
// ~ Instance fields
// ================================================================================================
private String rolePrefix = "ROLE_";
private GrantedAuthorityDefaults rolePrefix = new GrantedAuthorityDefaults("ROLE_");
private HttpServletRequestFactory requestFactory;
@@ -93,7 +98,7 @@ public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {
public void setRolePrefix(String rolePrefix) {
Assert.notNull(rolePrefix, "Role prefix must not be null");
this.rolePrefix = rolePrefix;
this.rolePrefix = new GrantedAuthorityDefaults(rolePrefix);
updateFactory();
}
@@ -177,8 +182,9 @@ public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {
}
private void updateFactory() {
this.requestFactory = isServlet3() ? createServlet3Factory(this.rolePrefix)
: new HttpServlet25RequestFactory(this.trustResolver, this.rolePrefix);
String rolePrefix = this.rolePrefix.getRolePrefix();
this.requestFactory = isServlet3() ? createServlet3Factory(rolePrefix)
: new HttpServlet25RequestFactory(this.trustResolver, rolePrefix);
}
/**
@@ -210,4 +216,14 @@ public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {
private boolean isServlet3() {
return ClassUtils.hasMethod(ServletRequest.class, "startAsync");
}
@Override
public void setApplicationContext(ApplicationContext context) throws
BeansException {
String[] beanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class);
if (beanNames.length == 1) {
this.rolePrefix = context.getBean(beanNames[0], GrantedAuthorityDefaults.class);
}
}
}
@@ -33,6 +33,7 @@ import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.config.GrantedAuthorityDefaults;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.FilterInvocation;
@@ -62,7 +63,7 @@ public class DefaultWebSecurityExpressionHandlerTests {
}
@Test
public void expressionPropertiesAreResolvedAgainsAppContextBeans() throws Exception {
public void expressionPropertiesAreResolvedAgainstAppContextBeans() throws Exception {
StaticApplicationContext appContext = new StaticApplicationContext();
RootBeanDefinition bean = new RootBeanDefinition(SecurityConfig.class);
bean.getConstructorArgumentValues().addGenericArgumentValue("ROLE_A");
@@ -95,4 +96,22 @@ public class DefaultWebSecurityExpressionHandlerTests {
verify(trustResolver).isAnonymous(authentication);
}
@Test
public void testDefaultRolePrefix() {
StaticApplicationContext appContext = new StaticApplicationContext();
RootBeanDefinition bean = new RootBeanDefinition(GrantedAuthorityDefaults.class);
bean.getConstructorArgumentValues().addGenericArgumentValue("ROL_");
appContext.registerBeanDefinition("authorityDefaults", bean);
handler.setApplicationContext(appContext);
EvaluationContext ctx = handler.createEvaluationContext(
mock(Authentication.class), mock(FilterInvocation.class));
ExpressionParser parser = handler.getExpressionParser();
assertThat(parser.parseExpression("@authorityDefaults.getRolePrefix() == 'ROL_'").getValue(
ctx, Boolean.class)).isTrue();
assertThat(parser.parseExpression("@authorityDefaults.rolePrefix == 'ROL_'").getValue(ctx,
Boolean.class)).isTrue();
}
}
@@ -36,6 +36,9 @@ import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.internal.WhiteboxImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
@@ -43,11 +46,13 @@ import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.concurrent.DelegatingSecurityContextRunnable;
import org.springframework.security.config.GrantedAuthorityDefaults;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.util.ClassUtils;
import static org.assertj.core.api.Assertions.assertThat;
@@ -67,6 +72,7 @@ import static org.powermock.api.mockito.PowerMockito.when;
*
* @author Ben Alex
* @author Rob Winch
* @author Eddú Meléndez
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassUtils.class)
@@ -195,7 +201,7 @@ public class SecurityContextHolderAwareRequestFilterTests {
// SEC-2296
@Test
public void loginWithExstingUser() throws Exception {
public void loginWithExistingUser() throws Exception {
TestingAuthenticationToken expectedAuth = new TestingAuthenticationToken("user",
"password", "ROLE_USER");
when(this.authenticationManager
@@ -415,4 +421,31 @@ public class SecurityContextHolderAwareRequestFilterTests {
return this.requestCaptor.getValue();
}
@Test
public void testDefaultRolePrefix() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(FilterConfiguration.class);
context.refresh();
SecurityContextHolderAwareRequestFilter filter = context.getBean(SecurityContextHolderAwareRequestFilter.class);
GrantedAuthorityDefaults authorityDefaults = (GrantedAuthorityDefaults) ReflectionTestUtils.getField(filter, "rolePrefix");
assertThat(authorityDefaults.getRolePrefix()).isEqualTo("ROL_");
}
@Configuration
static class FilterConfiguration {
@Bean
public GrantedAuthorityDefaults authorityDefaults() {
return new GrantedAuthorityDefaults("ROL_");
}
@Bean
public SecurityContextHolderAwareRequestFilter requestFilter() {
return new SecurityContextHolderAwareRequestFilter();
}
}
}