spring-security Spring Security 3.2 -配置全局方法安全性以使用角色层次结构

wtlkbnrh  于 2022-11-11  发布在  Spring
关注(0)|答案(2)|浏览(198)

使用Spring安全3.2.5和Spring 4.1.2,100% Java配置

我们的Web应用程序启用了全局方法安全性,并使用@PreAuthorize注解了服务方法-一切都按预期工作。我尝试添加角色层次结构,但完全没有成功。下面是我尝试实现的层次结构:

  • ROLE_ADMIN可以访问ROLE_USER可以访问的所有方法。
  • ROLE_USER可以访问ROLE_DEFAULT可以访问的所有方法。

尽管我已尽了最大努力,但具有ROLE_ADMIN的用户在执行某些操作导致调用使用@PreAuthorized("hasAuthority('ROLE_DEFAULT')")注解的方法时仍会收到403
下面是相关的配置代码:

应用程序初始化程序

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{
  @Override
  protected Class<?>[] getRootConfigClasses()
  {
    return new Class[]
    {
      AppConfig.class, SecurityConfig.class
    };
  }

  @Override
  protected Class<?>[] getServletConfigClasses()
  {
    return new Class[]
    {
      MvcConfig.class
    };
  }
  // other methods not shown for brevity
}

应用程序配置.java

@Configuration
@ComponentScan(basePackages={"myapp.config.profile", "myapp.dao", "myapp.service", "myapp.security"})
public class AppConfig
{
  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth,
                              AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> detailSvc) throws Exception
  {
    PreAuthenticatedAuthenticationProvider authProvider = new PreAuthenticatedAuthenticationProvider();
    authProvider.setPreAuthenticatedUserDetailsService(detailSvc);
    auth.authenticationProvider(authProvider);
  }
  // other methods not shown for brevity
}

安全配置.java

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
  @Override
  protected void configure(HttpSecurity http) throws Exception
  {
    PKIAuthenticationFilter pkiFilter = new PKIAuthenticationFilter();
    pkiFilter.setAuthenticationManager(authenticationManagerBean());

    http.authorizeRequests()
        .antMatchers("/app/**").fullyAuthenticated()
        .and()
        .anonymous().disable()
        .jee().disable()
        .formLogin().disable()
        .csrf().disable()
        .x509().disable()
        .addFilter(pkiFilter)
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  }

  @Override
  public void configure(WebSecurity web) throws Exception
  {
    // ignore everything but /app/*
    web.ignoring().regexMatchers("^(?!/app/).*");
  }
}

移动vcConfig.java

@Configuration
@EnableWebMvc
@ComponentScan({"myapp.controller"})
public class MvcConfig extends WebMvcConfigurerAdapter
{
  // resource handlers, content negotiation, message converters configured here
}

在与SecurityConfig相同的包中(因此它是AppConfig组件扫描的一部分),我有这样的类:

全局方法安全配置.java

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class GlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration
{
  @Bean
  public RoleHierarchy roleHierarchy()
  {
    RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
    roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER > ROLE_DEFAULT");
    return roleHierarchy;
  }

  @Bean
  public RoleVoter roleVoter()
  {
    return new RoleHierarchyVoter(roleHierarchy);
  }

  @Bean
  @Override
  protected AccessDecisionManager accessDecisionManager()
  {
    return new AffirmativeBased(Arrays.asList(roleVoter()));
  }

  // The method below was added in an attempt to get things working but it is never called
  @Override
  protected MethodSecurityExpressionHandler createExpressionHandler()
  {
    DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
    handler.setRoleHierarchy(roleHierarchy());
    return handler;
  }
}

在另一次尝试中,我使AppConfig扩展GlobalMethodSecurityConfiguration,但是具有ROLE_ADMIN的用户无法调用需要ROLE_DEFAULT访问权限的方法。
我确信我在某个地方配置错了,但是尽管我阅读了所有关于使用角色层次结构配置全局方法安全性的内容,我还是找不到哪里出了问题。使用XML配置似乎很简单,但是Java配置解决方案让我很困惑。

yacmzcpb

yacmzcpb1#

由于这个问题不断得到意见,我想我会张贴一个后续行动。问题似乎是与行
roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER > ROLE_DEFAULT");
我不记得我为什么要这样写层次结构,但这是不正确的。该方法的API处理同样的情况:

**角色层次结构:**角色A〉角色B和角色B〉角色C。
**直接分配的权限:**ROLE_A。
**可访问的颁发机构:**ROLE_A、ROLE_B、ROLE_C。

最后,分层模型显然不适合我们的角色,因此我们实现了Map到角色的更细粒度的权限集,如Spring Security Reference:
对于更复杂的要求,您可能希望在应用程序所需的特定访问权限和分配给用户的角色之间定义一个逻辑Map,并在加载用户信息时在两者之间进行转换。

mec1mxoz

mec1mxoz2#

我会覆盖GlobalMethodSecurityConfiguration#accessDecisionManager方法。你可以看到RoleVoter使用的源代码。
下面是我建议的重写源代码。

@Override
    protected AccessDecisionManager accessDecisionManager() {
        var roleHierarchy = new RoleHierarchyImpl();
        roleHierarchy.setHierarchy("ROLE_SUPER > ROLE_ADMIN");

        var expressionHandler = (DefaultMethodSecurityExpressionHandler) getExpressionHandler();
        expressionHandler.setRoleHierarchy(roleHierarchy);

        var expressionAdvice = new ExpressionBasedPreInvocationAdvice();
        expressionAdvice.setExpressionHandler(expressionHandler);

        return new AffirmativeBased(List.of(
                new RoleHierarchyVoter(roleHierarchy),
                new PreInvocationAuthorizationAdviceVoter(expressionAdvice),
                new AuthenticatedVoter(),
                new Jsr250Voter()
        ));
    }

相关问题