带有 Java 配置和 Spring Security 3.2 的安全方法注释

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19353578/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 16:23:48  来源:igfitidea点击:

Security Method Annotations with Java Configuration and Spring Security 3.2

javaspringspring-mvcspring-securityannotations

提问by Luke

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

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

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

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

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

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

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

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

One configuration was the following.

一种配置如下。

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

As far as I am aware @EnableGlobalMethodSecuritysets up its own AuthenticationManagerso I'm not sure what the problem is here.

据我所知,@EnableGlobalMethodSecurity设置了自己的AuthenticationManager所以我不确定这里的问题是什么。

The second configuration is as follows.

第二种配置如下。

@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.

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

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.

我已经研究了几天了,即使在深入研究 spring 安全实现代码之后,我似乎也找不到我的配置有什么问题。

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

我正在使用 spring-security-3.2.0.RC1 和 spring-framework-3.2.3.RELEASE。

采纳答案by Rob Winch

When you use the protected registerAuthenticationmethods on WebSecurityConfigurerAdapterit is scoping the Authentication to that WebSecurityConfigurerAdapterso EnableGlobalMethodSecuritycannot find it. If you think about this...it makes sense since the method is protected.

当您使用其protected registerAuthentication上的方法时,WebSecurityConfigurerAdapter会将身份验证范围限定为该范围,WebSecurityConfigurerAdapter因此EnableGlobalMethodSecurity无法找到它。如果您考虑一下……这是有道理的,因为该方法是受保护的。

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 EnableGlobalMethodSecuritywill try the following ways to try and get the AuthenticationManager:

您看到的错误实际上是一个调试语句(注意级别是调试)。原因是 Spring Security 会尝试几种不同的方式来自动连接 Global Method Security。具体EnableGlobalMethodSecurity会尝试以下方式尝试获取AuthenticationManager

  • If you extend GlobalMethodSecurityConfigurationand override the registerAuthenticationit will use the AuthenticationManagerBuilderthat was passed in. This allows for isolating the AuthenticationManagerin 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 AuthenticationManagerthat is exposed as a bean.
  • 如果您扩展GlobalMethodSecurityConfiguration并覆盖registerAuthentication它,它将使用AuthenticationManagerBuilder传入的 。这允许以AuthenticationManager与您可以使用的相同方式隔离WebSecurityConfigurerAdapter
  • 尝试从 的全局共享实例构建AuthenticationManagerBuilder,如果失败,它会记录您看到的错误消息(注意日志还指出“现在可以了,我们将尝试直接使用 AuthenticationManager”)
  • 尝试使用AuthenticationManager作为 bean 公开的 。

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.

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