spring-security 如何从默认的HttpSecurity中删除AbstractHttpConfigurer

rryofs0p  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(169)

我正在创建一个内部库,并且我希望执行一些自动配置,包括删除默认添加的安全定制器,例如LogoutConfigurer,就好像它不是默认HttpSecurity原型bean的一部分:

@Bean
    public SecurityFilterChain authFilter(HttpSecurity http) throws Exception {
        return http
                   // I want to make this unnecessary by not being part of the (adjusted) HttpSecurity
                   //.logout().disable()
                   .authorizeRequests()
                   .mvcMatchers("/secured").hasRole("ROLE")
                   .anyRequest().denyAll()
                   .and()
                   .build(); // (1)
    }

以横切方式自定义安全性的方法似乎是实现AbstractHttpConfigurer bean,但这些bean仅作为HttpScurity#build()方法的一部分触发,该方法生成SecurityFilterChain作为主应用程序安全配置代码的一部分(上面标记为(1))。这已经太晚了,因为我的bean需要撤消之前另一个定制器所做的配置,这是复杂的并且可能是不可能的(去除过滤器等)。
到目前为止,我找到的唯一替代方法似乎是重写AbstractHttpConfigurer#setBuilder(B),以操纵给定的构建器(HttpSecurity对象)删除定制器,假定在创建HttpSecurity之后并在使其作为原型bean可访问之前调用此方法:

public class MyHttpConfigurer extends AbstractHttpConfigurer<MyHttpConfigurer, HttpSecurity> {

    @Override
    public final void setBuilder(HttpSecurity http) {
        super.setBuilder(http);

        try {
            // Do this and/or whatever else you want to do
            http.logout().disable();
        } catch (Exception e) {
            throw new RuntimeException("It failed", e);
        }
    }

    @Override
    public final void configure(final HttpSecurity http) throws Exception {}
}

它按照我想要的那样工作,但看起来不稳定,滥用API,感觉它可能会在没有警告的情况下崩溃。我也没有找到替换默认HttpSecurity原型构建器的方法,因为它不是有条件的。
是否有更干净或有文档记录的方法来实现这一点?

cs7cruho

cs7cruho1#

我认为实现功能的最简洁的方法是提供一个BeanPostProcessor
例如:

@Configuration(proxyBeanMethods = false)
public class CustomSecurityConfiguration {

    private static final String HTTP_SECURITY_DEFAULT_BEAN_NAME = "org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity";

    @Bean
    public static BeanPostProcessor httpSecurityBeanPostProcessor() {
        return new BeanPostProcessor() {

            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof HttpSecurity && HTTP_SECURITY_DEFAULT_BEAN_NAME.equals(beanName)) {
                    HttpSecurity http = (HttpSecurity) bean;
                    try {
                        http.logout().disable();
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
                return bean;
            }
        };
    }

}

这和你提出的例子非常相似,我不认为它是在滥用API,因为它允许访问HttpSecurity

相关问题