简体   繁体   English

Spring Security 从其他 jar 扩展配置

[英]Spring Security extend configuration from other jar

I have an application that has dependency where the security is defined.我有一个具有依赖关系的应用程序,其中定义了安全性。 Typical config:典型配置:

@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());
    }
}

The above is the first project.以上是第一个项目。 And I have a second project where I have a POM dependency for this above.我有第二个项目,我在上面有一个 POM 依赖项。 Now I would like to add an additional user, but I have to do this in my second project where there is just dependency to the first project with security.现在我想添加一个额外的用户,但我必须在我的第二个项目中执行此操作,其中仅依赖于第一个具有安全性的项目。

I can copy&paste the whole AuthConfiguration, then I have 2 security filter chains but it is rather a bad idea.我可以复制并粘贴整个 AuthConfiguration,然后我有 2 个安全过滤器链,但这不是一个好主意。 The app starts processing requests looking at what destination URI is.应用开始处理请求,查看目标 URI 是什么。 Two filter chains have the same antMatchers (I only want to add additional users) and only one filter chain is being processed.两个过滤器链具有相同的 antMatcher(我只想添加额外的用户)并且只处理一个过滤器链。 As a result, it works partially - user from the first or second project works (it depends on @Order of AuthConfiguration).因此,它部分工作 - 来自第一个或第二个项目的用户工作(这取决于 AuthConfiguration 的 @Order)。

Maybe somehow it is possible to inject for instance AuthenticationManagerBuilder in my second project and extend/add additional users?也许以某种方式可以在我的第二个项目中注入例如 AuthenticationManagerBuilder 并扩展/添加其他用户? I tried but it does not work.我试过了,但它不起作用。 I added such code in the second project:我在第二个项目中添加了这样的代码:

@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());
    }
}

Only first user FOO works, what looks like it is from the first project where it is defined.只有第一个用户 FOO 有效,看起来它来自定义它的第一个项目。

Edit: I tried also approach from this question How can I add users to the inMemoryAuthentication builder after it has been built?编辑:我也尝试了这个问题的方法How can I add users to the inMemoryAuthentication builder after it has been built? I added this code in my second project:我在我的第二个项目中添加了这段代码:

@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]
    }
}

It looks good.这看起来不错的样子。 In debugger (comment in code) I see user from the first project and new user.在调试器(代码注释)中,我看到来自第一个项目的用户和新用户。 But when I request endpoint with postman I see internally in debugger how it calls to InMemoryUserDetailsManager::loadByUsername() and this manager has different instance than where I added user two.但是当我使用 postman 请求端点时,我在调试器内部看到它如何调用 InMemoryUserDetailsManager::loadByUsername() 并且这个管理器的实例与我添加用户 2 的实例不同。 And it only has one user from the first project.它只有一个来自第一个项目的用户。 When I start app with debbuger I see that firstly is executed my above code where I add second user, and then is executed code from the first project (AuthConfiguration class) where AuthenticationManagerBuilder::inMemoryAuthentication goes to InMemoryUserDetailsManagerConfigurer where creates new instance of InMemoryUserDetailsManager using new keyword.当我使用 debbuger 启动应用程序时,我看到首先执行我上面的代码,在其中添加第二个用户,然后从第一个项目(AuthConfiguration 类)执行代码,其中 AuthenticationManagerBuilder::inMemoryAuthentication 转到 InMemoryUserDetailsManagerConfigurer,其中使用new创建 InMemoryUserDetailsManager 的新实例关键词。

Finally in my second project I just extended AuthConfiguration class from the first project in this way:最后,在我的第二个项目中,我只是以这种方式从第一个项目中扩展了 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());
    }   
}

and it works correctly.它工作正常。 Order(90) was needed also because AuthConfiguration has default Order 100, and it was stopping application with errors on start. Order(90)也是需要的,因为 AuthConfiguration 具有默认的 Order 100,并且它在启动时停止应用程序并出现错误。 Very simple approach but tried it as last.非常简单的方法,但最后尝试了。

Another approach you can take is to use a custom bean (say UserFactory) to your configuration in the first project and use it to retrieve all the users and add to in-memory user manager您可以采用的另一种方法是在第一个项目中对您的配置使用自定义 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);
            }
        }
    }

And in your second project, you define the bean and add the additional users:在您的第二个项目中,您定义 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;
    }

This might suit better if you have many default users and want to avoid re-typing them in the extended configuration class.如果您有许多默认用户并希望避免在扩展配置类中重新键入它们,这可能更适合。

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

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