繁体   English   中英

Spring Security 从其他 jar 扩展配置

[英]Spring Security extend configuration from other jar

我有一个具有依赖关系的应用程序,其中定义了安全性。 典型配置:

@Configuration
@EnableWebSecurity
public class AuthConfiguration extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers(DEFAULT_PERMIT_ALL_PATHS).permitAll()
            .and()
            .authorizeRequests().anyRequest().authenticated()
            .and()
            .exceptionHandling()
            .and()
            .csrf().disable().httpBasic();
    }        

    @Override
    protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
        User.UserBuilder users = User.withDefaultPasswordEncoder();
        authManagerBuilder.inMemoryAuthentication().withUser(users.username("FOO").password("BAR").roles("USER").build());
    }
}

以上是第一个项目。 我有第二个项目,我在上面有一个 POM 依赖项。 现在我想添加一个额外的用户,但我必须在我的第二个项目中执行此操作,其中仅依赖于第一个具有安全性的项目。

我可以复制并粘贴整个 AuthConfiguration,然后我有 2 个安全过滤器链,但这不是一个好主意。 应用开始处理请求,查看目标 URI 是什么。 两个过滤器链具有相同的 antMatcher(我只想添加额外的用户)并且只处理一个过滤器链。 因此,它部分工作 - 来自第一个或第二个项目的用户工作(这取决于 AuthConfiguration 的 @Order)。

也许以某种方式可以在我的第二个项目中注入例如 AuthenticationManagerBuilder 并扩展/添加其他用户? 我试过了,但它不起作用。 我在第二个项目中添加了这样的代码:

@Configuration
public class AdditionalUsersConfiguration() {

    public AdditionalUsersConfiguration(AuthenticationManagerBuilder builder) throws Exception {
        User.UserBuilder users = User.withDefaultPasswordEncoder();

        authManagerBuilder.inMemoryAuthentication()
        .withUser(users.username("FOO").password("BAR").roles("USER")
        .withUser(users.username("FOO2").password("BAR").roles("USER").build());
    }
}

只有第一个用户 FOO 有效,看起来它来自定义它的第一个项目。

编辑:我也尝试了这个问题的方法How can I add users to the inMemoryAuthentication builder after it has been built? 我在我的第二个项目中添加了这段代码:

@Configuration
public class NextApproachConfiguration() {

    public NextApproachConfiguration(InMemoryUserDetailsManager manager) throws Exception {
        manager.createUser(new User("FOO2", "BAR", new ArrayList<GrantedAuthority>()));
        // in debugger here I see two users [FOO, FOO2]
    }
}

这看起来不错的样子。 在调试器(代码注释)中,我看到来自第一个项目的用户和新用户。 但是当我使用 postman 请求端点时,我在调试器内部看到它如何调用 InMemoryUserDetailsManager::loadByUsername() 并且这个管理器的实例与我添加用户 2 的实例不同。 它只有一个来自第一个项目的用户。 当我使用 debbuger 启动应用程序时,我看到首先执行我上面的代码,在其中添加第二个用户,然后从第一个项目(AuthConfiguration 类)执行代码,其中 AuthenticationManagerBuilder::inMemoryAuthentication 转到 InMemoryUserDetailsManagerConfigurer,其中使用new创建 InMemoryUserDetailsManager 的新实例关键词。

最后,在我的第二个项目中,我只是以这种方式从第一个项目中扩展了 AuthConfiguration 类:

@Configuration
@Order(90)
public class SecondProjectConfiguration extends AuthConfiguration {

    @Override
    protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
        super.configure(authManagerBuilder); // it creates FOO user

        User.UserBuilder users = User.withDefaultPasswordEncoder();
        authManagerBuilder.inMemoryAuthentication()
            .withUser(users.username("FOO2").password("BAR").roles("USER").build());
    }   
}

它工作正常。 Order(90)也是需要的,因为 AuthConfiguration 具有默认的 Order 100,并且它在启动时停止应用程序并出现错误。 非常简单的方法,但最后尝试了。

您可以采用的另一种方法是在第一个项目中对您的配置使用自定义 bean(例如 UserFactory),并使用它来检索所有用户并添加到内存用户管理器

    @Autowired(required = false)
    UserFactory userFactory;

    @Override
    protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
        User.UserBuilder users = User.withDefaultPasswordEncoder();
        InMemoryUserDetailsManagerConfigurer configurer = authManagerBuilder.inMemoryAuthentication();
        configurer.withUser(users.username("FOO").password("BAR").roles("USER").build());
        if (userFactory != null) {
            for (UserDetails userDetails: userFactory.getUsers()) {
                configurer.withUser(userDetails);
            }
        }
    }

在您的第二个项目中,您定义 bean 并添加其他用户:

    @Bean
    public UserFactory userFactory() {
        UserFactory userFactory = new UserFactory();
        User.UserBuilder user = User.withDefaultPasswordEncoder();
        userFactory.addUser(user.username("FOO2").password("BAR").roles("USER").build());
        return userFactory;
    }

如果您有许多默认用户并希望避免在扩展配置类中重新键入它们,这可能更适合。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM