禁用EnableGlobalMethodSecurity批注

时间:2014-03-04 15:34:20

标签: java spring spring-security

有没有办法可以使用config.properties中的boolean securityEnabled来禁用全局方法安全性?还有其他方法吗?

@EnableWebSecurity 
@EnableGlobalMethodSecurity(securedEnabled=true) 
@PropertySource("classpath:config.properties")  
public class SecurityConfig 
  extends WebSecurityConfigurerAdapter {    

  @Value("${securityconfig.enabled}") 
  private boolean securityEnabled;

  ...

}

4 个答案:

答案 0 :(得分:4)

最简单的方法是:

  • 将方法安全性提取到自己的类
  • 完全删除securedEnabled属性
  • 覆盖customMethodSecurityMetadataSource方法并根据配置的值返回结果。

例如:

@EnableWebSecurity
@Configuration
@PropertySource("classpath:config.properties")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    ...
}

@EnableGlobalMethodSecurity
@Configuration
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    @Value("${securityconfig.enabled}")
    private boolean securityEnabled;

    protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
        return securityEnabled ? new SecuredAnnotationSecurityMetadataSource() : null;
    }    
}

答案 1 :(得分:1)

在 Springboot2 中,一个简单的解决方案是在安全性关闭时将安全性方法拦截器替换为虚拟拦截器:

@EnableGlobalMethodSecurity(prePostEnabled = true)
static class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    @Value("${disableSecurity}")
    private boolean disableSecurity;  

    public MethodInterceptor methodSecurityInterceptor(MethodSecurityMetadataSource methodSecurityMetadataSource) {
        return disableSecurity ? new SimpleTraceInterceptor()
                : super.methodSecurityInterceptor(methodSecurityMetadataSource);
    }

}

答案 2 :(得分:0)

我已经通过定义一个Spring“ securityDisabled”配置文件并有条件地应用安全配置来解决这个问题。我正在使用Spring Boot 2.0.2。我相信,如果不使用Spring Boot和以前的Spring Boot版本,这应该可以工作,但是我还没有测试过。可能需要对属性和类名进行一些调整,因为我知道在Spring 2.0中,其中一些更改。

// In application.properties (could also based in via command line or environment variable)
spring.profiles.active=securityDisabled
// Or even with
spring.profiles.include=securityDisabled

然后我的安全配置如下:

@Configuration
public class SecurityConfig {

  // When the securityDisabled profile is applied the following configuration gets used
  @Profile("securityDisabled")
  @EnableWebSecurity
  public class SecurityDisabledConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // Configure http as needed from Spring Security defaults when
        // NO security is desired
    }
  }

  // When the securityDisabled profile is NOT applied the following configuration gets used
  @Profile("!securityDisabled")
  @EnableGlobalMethodSecurity(prePostEnabled = true)
  @EnableWebSecurity
  public class SecurityEnabledConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // Configure http as needed from Spring Security defaults when
        // security is desired
    }
  }
}

答案 3 :(得分:0)

感谢Rob Winch提供解决方案。对于想做类似的事情但使用prePostEnabled的人,我已经尝试并测试了以下类似方法,并且效果很好。

@EnableGlobalMethodSecurity(securedEnabled = true)
@Configuration
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

  @Value("${security.prePostEnabled}")
  private boolean prePostEnabled;

 @Autowired
private DefaultMethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler;

  protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
     return prePostEnabled ? new PrePostAnnotationSecurityMetadataSource(new ExpressionBasedAnnotationAttributeFactory(defaultMethodSecurityExpressionHandler)) : null ;
}}

编辑:除上述以外,我意识到还需要向该类中添加以下bean。下面将帮助使用基于表达式的预调用检查,以及避免在所有处理程序中默认使用的“ ROLE_”前缀

protected AccessDecisionManager accessDecisionManager() {
    AffirmativeBased accessDecisionManager = (AffirmativeBased) super.accessDecisionManager();
    ExpressionBasedPreInvocationAdvice expressionAdvice = new ExpressionBasedPreInvocationAdvice();
    expressionAdvice.setExpressionHandler(getExpressionHandler());
    //This is required in order to allow expression based Voter to allow access
    accessDecisionManager.getDecisionVoters()
            .add(new PreInvocationAuthorizationAdviceVoter(expressionAdvice));

    //Remove the ROLE_ prefix from RoleVoter for @Secured and hasRole checks on methods
    accessDecisionManager.getDecisionVoters().stream()
            .filter(RoleVoter.class::isInstance)
            .map(RoleVoter.class::cast)
            .forEach(it -> it.setRolePrefix(""));

    return accessDecisionManager;
}
/**
 * Allow skip ROLE_ when check permission using @PreAuthorize, like:
 * @PreAuthorize("hasAnyRole('USER', 'SYSTEM_ADMIN')")
 * Added all the Beans
 */
@Bean
public DefaultMethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler() {
    DefaultMethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler = new DefaultMethodSecurityExpressionHandler();
    defaultMethodSecurityExpressionHandler.setDefaultRolePrefix("");
    return defaultMethodSecurityExpressionHandler;
}