RoleHiearchy Bean used in GlobalMethodSecurity (#3394)
Previously it required quite a bit of extra work to use RoleHiearchy within Java Based Spring Security configuration. Now if a single RoleHiearchy Bean is defined it will automatically be picked up and used by method security. Fixes gh-3394
This commit is contained in:
parent
933a7e8363
commit
c872a77ad1
|
@ -43,6 +43,7 @@ import org.springframework.security.access.expression.method.ExpressionBasedAnno
|
|||
import org.springframework.security.access.expression.method.ExpressionBasedPostInvocationAdvice;
|
||||
import org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.security.access.intercept.AfterInvocationManager;
|
||||
import org.springframework.security.access.intercept.AfterInvocationProviderManager;
|
||||
import org.springframework.security.access.intercept.RunAsManager;
|
||||
|
@ -333,6 +334,11 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
|||
this.defaultMethodExpressionHandler.setTrustResolver(trustResolver);
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setRoleHierarchy(RoleHierarchy roleHierarchy){
|
||||
this.defaultMethodExpressionHandler.setRoleHierarchy(roleHierarchy);
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
|
||||
this.objectPostProcessor = objectPostProcessor;
|
||||
|
|
|
@ -20,10 +20,12 @@ import java.util.Collection;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.security.access.AccessDecisionVoter;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
|
@ -188,6 +190,14 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
|||
if (trustResolver != null) {
|
||||
defaultHandler.setTrustResolver(trustResolver);
|
||||
}
|
||||
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
|
||||
if(context != null) {
|
||||
String[] roleHiearchyBeanNames = context.getBeanNamesForType(RoleHierarchy.class);
|
||||
if(roleHiearchyBeanNames.length == 1) {
|
||||
defaultHandler.setRoleHierarchy(context.getBean(roleHiearchyBeanNames[0], RoleHierarchy.class));
|
||||
}
|
||||
}
|
||||
|
||||
expressionHandler = postProcess(defaultHandler);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
*/
|
||||
package org.springframework.security.config.annotation.method.configuration
|
||||
|
||||
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import org.junit.After;
|
||||
|
@ -470,4 +474,26 @@ public class GlobalMethodSecurityConfigurationTests extends BaseSpringSpec {
|
|||
return arg;
|
||||
}
|
||||
}
|
||||
|
||||
// gh-3394
|
||||
def roleHierarchy() {
|
||||
setup:
|
||||
SecurityContextHolder.getContext().setAuthentication(
|
||||
new TestingAuthenticationToken("user", "password","ROLE_USER"))
|
||||
context = new AnnotationConfigApplicationContext(RoleHierarchyConfig)
|
||||
MethodSecurityService service = context.getBean(MethodSecurityService)
|
||||
when:
|
||||
service.preAuthorizeAdmin()
|
||||
then:
|
||||
noExceptionThrown()
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
@Configuration
|
||||
public static class RoleHierarchyConfig extends BaseMethodConfig {
|
||||
@Bean
|
||||
RoleHierarchy roleHierarchy() {
|
||||
return new RoleHierarchyImpl(hierarchy:"ROLE_USER > ROLE_ADMIN")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,9 @@ public interface MethodSecurityService {
|
|||
@PreAuthorize("permitAll")
|
||||
public String preAuthorizePermitAll();
|
||||
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
public void preAuthorizeAdmin();
|
||||
|
||||
@PreAuthorize("hasPermission(#object,'read')")
|
||||
public String hasPermission(String object);
|
||||
|
||||
|
|
|
@ -55,6 +55,10 @@ public class MethodSecurityServiceImpl implements MethodSecurityService {
|
|||
return SecurityContextHolder.getContext().getAuthentication();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preAuthorizeAdmin() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String preAuthorizePermitAll() {
|
||||
return null;
|
||||
|
|
|
@ -22,16 +22,24 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.web.MockFilterChain;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
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.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextImpl;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
@ -198,6 +206,48 @@ public class AuthorizeRequestsTests {
|
|||
}
|
||||
}
|
||||
|
||||
// gh-3394
|
||||
@Test
|
||||
public void roleHiearchy() throws Exception {
|
||||
loadConfig(RoleHiearchyConfig.class);
|
||||
|
||||
SecurityContext securityContext = new SecurityContextImpl();
|
||||
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("test", "notused", AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
this.request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, securityContext);
|
||||
|
||||
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||
|
||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class RoleHiearchyConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().hasRole("ADMIN");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.inMemoryAuthentication();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RoleHierarchy roleHiearchy() {
|
||||
RoleHierarchyImpl result = new RoleHierarchyImpl();
|
||||
result.setHierarchy("ROLE_USER > ROLE_ADMIN");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public void loadConfig(Class<?>... configs) {
|
||||
this.context = new AnnotationConfigWebApplicationContext();
|
||||
this.context.register(configs);
|
||||
|
|
Loading…
Reference in New Issue