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

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

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

我尝试了两种不同的方法来初始化AuthenticationManager和它们自己的问题。 请注意, 使用@EnableGlobalMethodSecurity导致服务器启动成功,并且所有表单安全性都按预期执行。 当我在@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"); } } } 

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

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

此配置实际上已成功启动但有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.(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.RELEASE。

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

您看到的错误实际上是一个调试语句(注意级别是DEBUG)。 原因是Spring Security将尝试使用几种不同的方法来自动连接Global Method Security。 具体来说, 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(); } } } 

注意:有关此内容的更多文档将在未来几天内添加到参考中。