【问题标题】:Spring Security extend configuration from other jarSpring Security 从其他 jar 扩展配置
【发布时间】:2021-12-21 05:30:22
【问题描述】:

我有一个应用程序,该应用程序具有定义安全性的依赖项。典型配置:

@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 是什么。两个过滤器链具有相同的 antMatchers(我只想添加其他用户),并且只处理一个过滤器链。结果,它部分工作 - 第一个或第二个项目的用户工作(它取决于 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]
    }
}

看起来不错。在调试器(代码中的注释)中,我看到来自第一个项目的用户和新用户。但是当我向邮递员请求端点时,我在调试器内部看到它如何调用 InMemoryUserDetailsManager::loadByUsername() 并且该管理器的实例与我添加用户二的位置不同。它只有一个来自第一个项目的用户。 当我使用调试器启动应用程序时,我看到首先在我添加第二个用户的地方执行我的上述代码,然后从第一个项目(AuthConfiguration 类)执行代码,其中 AuthenticationManagerBuilder::inMemoryAuthentication 转到 InMemoryUserDetailsManagerConfigurer 使用 新关键字。

【问题讨论】:

  • @xerx593:我试过了。这是行不通的。我不明白。我注入 InMemoryUserDetailsManager 并调用 .createUser()。我看到有 2 个用户(一个来自第一个 .jar,第二个来自此代码)。它看起来正确。但后来我使用邮递员请求端点,我在调试器中看到它尝试 InMemoryUserDetailsManager::loadByUsername(),但 InMemoryUserDetailsManager 是一个不同的实例,只有一个用户来自第一个 .jar。
  • ..您必须在“设置安全性”之前/同时添加它(即以正确的顺序):您将覆盖void configure(AuthenticationManagerBuilder a) ...理想情况下(/additonally)您可以访问( “lib”将公开)“用户详细信息管理器”bean...
  • 您可以发布(并接受)自己的答案! ;)

标签: java spring spring-security


【解决方案1】:

最后,在我的第二个项目中,我以这种方式从第一个项目中扩展了 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,并且它正在停止应用程序并在启动时出现错误。非常简单的方法,但最后尝试了。

【讨论】:

    【解决方案2】:

    您可以采取的另一种方法是在第一个项目中对您的配置使用自定义 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;
        }
    

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

    【讨论】:

      猜你喜欢
      • 2013-03-09
      • 2015-08-27
      • 2020-02-07
      • 2020-05-31
      • 2015-12-24
      • 1970-01-01
      • 2015-07-30
      • 2013-04-16
      • 2014-10-14
      相关资源
      最近更新 更多