与Java配置和春季安全3.2安全方法注释 [英] Security Method Annotations with Java Configuration and Spring Security 3.2

查看:354
本文介绍了与Java配置和春季安全3.2安全方法注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些问题让我的应用程序中设置使用由 @EnableGlobalMethodSecurity 控制方法级别的注释,我使用的Servlet 3.0风格的初始化使用

I am having some issues getting my application set up using method level annotation controlled by @EnableGlobalMethodSecurity I am using Servlet 3.0 style initialization using

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

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

我已经尝试2个不同的自己的问题初始化一个的AuthenticationManager 这两个办法。请注意的的使用 @EnableGlobalMethodSecurity 导致一个成功的服务器启动时,所有的形式如预期的安全执行的。我的出现问题时,我想补充 @EnableGlobalMethodSecurity @ preAuthorize(hasRole('ROLE_USER'))我控制器上标注。

I have attempted 2 different ways of initialising an AuthenticationManager both with their own issues. Please note that not using @EnableGlobalMethodSecurity results in a successful server start up and all of the form security executes as expected. My issues arise when I add @EnableGlobalMethodSecurity and @PreAuthorize("hasRole('ROLE_USER')") annotations on my controller.

我试图独立设置形式和基于API的安全性。基于方法注释只需要为API安全工作。

I am attempting to set up form-based and api-based security independently. The method based annotations need only work for the api security.

一种结构是以下

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

}

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

This is not ideal as I really want only a single registration of the authentication mechanism but the main issue is that it results in the following exception:

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

据我所知 @EnableGlobalMethodSecurity 建立自己的的AuthenticationManager 所以我不知道是什么问题就在这里。

As far as I am aware @EnableGlobalMethodSecurity sets up its own AuthenticationManager so I'm not sure what the problem is here.

第二配置如下

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

}

这实际上配置成功启动但有一个例外

This config actually starts successfully but with an exception

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)

和当我测试我发现,安全是行不通的。

and when I test I found that the security doesn't work.

我一直在看这几天,甚至潜入春季安全实现code后,我似乎无法找到什么不对我的配置。

I've been looking at this for a couple of days now and even after diving into spring security implementation code I can't seem to find what is wrong with my configuration.

我使用弹簧安全3.2.0.RC1和弹簧骨架3.​​2.3.RELEASE。

I am using spring-security-3.2.0.RC1 and spring-framework-3.2.3.RELEASE.

推荐答案

当您使用 WebSecurityConfigurerAdapter 保护registerAuthentication 方法C>是范围界定身份验证到 WebSecurityConfigurerAdapter 所以 EnableGlobalMethodSecurity 无法找到它。如果你想想这...这是有道理的,因为该方法是受保护的。

When you use the protected registerAuthentication methods on WebSecurityConfigurerAdapter it is scoping the Authentication to that WebSecurityConfigurerAdapter so EnableGlobalMethodSecurity cannot find it. If you think about this...it makes sense since the method is protected.

您所看到的错误实际上是一个调试语句(注意水平DEBUG)。究其原因是Spring Security会尝试一些不同的方式来自动接线全局方法的安全性。具体来说 EnableGlobalMethodSecurity 将尝试以下方法来尝试并获得的AuthenticationManager

The error you are seeing is actually a debug statement (note the level is DEBUG). The reason is that Spring Security will try a few different ways to automatically wire the Global Method Security. Specifically EnableGlobalMethodSecurity will try the following ways to try and get the AuthenticationManager:


  • 如果您延长 GlobalMethodSecurityConfiguration 并重写 registerAuthentication 它将使用 AuthenticationManagerBuilder 中传递。这样可以隔离的AuthenticationManager 以同样的方式,你可以用 WebSecurityConfigurerAdapter

  • 尝试从 AuthenticationManagerBuilder 全球共享实例来构建,如果失败,将您看到的错误信息(注意日志还注明:这是确定的,现在,我们将尝试使用直接AuthenticationManager会)

  • 尝试使用一个的AuthenticationManager 公开为一个bean。

  • If you extend GlobalMethodSecurityConfiguration and override the registerAuthentication it will use the AuthenticationManagerBuilder that was passed in. This allows for isolating the AuthenticationManager in the same way you can do so with WebSecurityConfigurerAdapter
  • Try to build from the global shared instance of AuthenticationManagerBuilder, if it fails it logs the error message you are seeing (Note the logs also state "This is ok for now, we will try using an AuthenticationManager directly")
  • Try to use an AuthenticationManager that is exposed as a bean.

有关您的code,你要成为最好关闭​​使用类似以下内容:

For your code, you are going to be best off using something like the following:

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

}

请注意:更多围绕这个文件将被添加到该参考在未来几天

NOTE: More documentation around this will be getting added to the reference in the coming days.

这篇关于与Java配置和春季安全3.2安全方法注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆