有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

使用Java配置和Spring Security 3.2的安全方法注释

我在使用由@EnableGlobalMethodSecurity控制的方法级注释设置应用程序时遇到了一些问题。我正在使用Servlet 3.0样式的初始化

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

    public SecurityWebApplicationInitializer() {
        super(MultiSecurityConfig.class);
    }
}

我尝试了两种不同的初始化AuthenticationManager的方法,这两种方法都有各自的问题。请注意,而不是使用@EnableGlobalMethodSecurity会导致服务器成功启动,并且所有表单安全性都会按预期执行。当我在控制器上添加@EnableGlobalMethodSecurity@PreAuthorize("hasRole('ROLE_USER')")注释时,会出现问题

我正在尝试独立设置基于表单和基于api的安全性。基于方法的注释只需要用于api安全性

一种配置如下所示

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class MultiSecurityConfig {

    @Configuration
    @Order(1)
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/api/**").httpBasic();
        }

        protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                .withUser("user").password("password").roles("USER").and()
                .withUser("admin").password("password").roles("USER", "ADMIN");
        }
    }

    @Configuration
    public static class FormWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/static/**","/status");
        }

        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().anyRequest().hasRole("USER").and()
                .formLogin().loginPage("/login").permitAll();
        }

        protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                .withUser("user").password("password").roles("USER").and()
                .withUser("admin").password("password").roles("USER", "ADMIN");
        }
    }

}

这并不理想,因为我真的只想注册一次身份验证机制,但主要问题是它会导致以下异常:

java.lang.IllegalArgumentException: Expecting to only find a single bean for type interface org.springframework.security.authentication.AuthenticationManager, but found []

据我所知@EnableGlobalMethodSecurity建立了自己的AuthenticationManager,所以我不确定这里有什么问题

第二种配置如下所示

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class MultiSecurityConfig {

    @Bean
    protected AuthenticationManager authenticationManager() throws Exception {
        return new AuthenticationManagerBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR)
                .inMemoryAuthentication()
                    .withUser("user").password("password").roles("USER").and()
                    .withUser("admin").password("password").roles("USER", "ADMIN").and()
                    .and()
                .build();
    }

    @Configuration
    @Order(1)
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
        @Override protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/api/**").httpBasic();
        }
    }

    @Configuration
    public static class FormWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/static/**","/status");
        }

        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().anyRequest().hasRole("USER").and()
                .formLogin().loginPage("/login").permitAll();
        }
    }

}

此配置实际上已成功启动,但出现异常

java.lang.IllegalArgumentException: A parent AuthenticationManager or a list of AuthenticationProviders is required
at org.springframework.security.authentication.ProviderManager.checkState(ProviderManager.java:117)
at org.springframework.security.authentication.ProviderManager.<init>(ProviderManager.java:106)
at org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder.performBuild(AuthenticationManagerBuilder.java:221)

当我测试时,我发现安全性不起作用

我已经研究这个问题好几天了,甚至在深入研究spring安全性实现代码之后,我似乎也找不到我的配置有什么问题

我正在使用spring-security-3.2.0。RC1和spring-framework-3.2.3。释放


共 (1) 个答案

  1. # 1 楼答案

    当您在WebSecurityConfigurerAdapter上使用protected registerAuthentication方法时,它将身份验证范围限定为WebSecurityConfigurerAdapter,因此EnableGlobalMethodSecurity无法找到它。如果你想想这个。。。这是有意义的,因为方法是受保护的

    您看到的错误实际上是一个调试语句(注意级别是debug)。原因是Spring安全性将尝试几种不同的方法来自动连接全局方法安全性。具体地说EnableGlobalMethodSecurity将尝试以下方法来获取AuthenticationManager

    • 如果扩展GlobalMethodSecurityConfiguration并重写registerAuthentication,它将使用传入的AuthenticationManagerBuilder。这允许以与WebSecurityConfigurerAdapter相同的方式隔离AuthenticationManager
    • 尝试从AuthenticationManagerBuilder的全局共享实例进行构建,如果失败,它会记录您看到的错误消息(请注意,日志还声明“现在还可以,我们将尝试直接使用AuthenticationManager”)
    • 尝试使用作为bean公开的AuthenticationManager

    对于您的代码,最好使用以下内容:

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled=true)
    public class MultiSecurityConfig {
        // Since MultiSecurityConfig does not extend GlobalMethodSecurityConfiguration and
        // define an AuthenticationManager, it will try using the globally defined
        // AuthenticationManagerBuilder to create one
    
        // The @Enable*Security annotations create a global AuthenticationManagerBuilder 
        // that can optionally be used for creating an AuthenticationManager that is shared
        // The key to using it is to use the @Autowired annotation
        @Autowired
        public void registerSharedAuthentication(AuthenticationManagerBuilder auth) throws Exception {
            auth
                .inMemoryAuthentication()
                    .withUser("user").password("password").roles("USER").and()
                    .withUser("admin").password("password").roles("USER", "ADMIN");
        }
    
        @Configuration
        @Order(1)
        public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
            // Since we didn't specify an AuthenticationManager for this class,
            // the global instance is used
    
    
            protected void configure(HttpSecurity http) throws Exception {
                http
                    .antMatcher("/api/**")
                    .httpBasic();
            }
        }
    
        @Configuration
        public static class FormWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
            // Since we didn't specify an AuthenticationManager for this class,
            // the global instance is used
    
            public void configure(WebSecurity web) throws Exception {
                web
                    .ignoring()
                        .antMatchers("/static/**","/status");
            }
    
            protected void configure(HttpSecurity http) throws Exception {
                http
                    .authorizeRequests()
                        .anyRequest().hasRole("USER")
                        .and()
                    .formLogin()
                        .loginPage("/login")
                        .permitAll();
            }
        }
    
    }
    

    注意:在接下来的几天里,更多关于这方面的文档将被添加到参考中