我在使用由@EnableGlobalMethodSecurity
控制的方法级别注释来设置我的应用程序时遇到一些问题,我正在使用Servlet 3.0样式初始化,
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
public SecurityWebApplicationInitializer() {
super(MultiSecurityConfig.class);
}
}
我尝试了两种不同的初始化
AuthenticationManager
的方式,它们都有各自的问题。请注意,不使用@EnableGlobalMethodSecurity
会导致服务器成功启动,并且所有表单安全性都将按预期执行。当我在 Controller 上添加@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();
}
}
}
该配置实际上成功启动,但有一个异常(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)
当我测试时发现安全性不起作用。
我已经研究了几天,甚至在深入研究Spring Security实现代码后,我似乎也找不到我的配置出了什么问题。
我正在使用spring-security-3.2.0.RC1和spring-framework-3.2.3.RELEASE。
最佳答案
当您在protected registerAuthentication
上使用WebSecurityConfigurerAdapter
方法时,它会将身份验证的作用域限定在该WebSecurityConfigurerAdapter
上,因此EnableGlobalMethodSecurity
找不到它。如果您考虑一下……这是有道理的,因为该方法受到保护。
您看到的错误实际上是一个调试语句(请注意级别为DEBUG)。原因是Spring Security将尝试几种不同的方法来自动连接Global Method Security。具体来说,EnableGlobalMethodSecurity
将尝试以下方式尝试获取AuthenticationManager
:
GlobalMethodSecurityConfiguration
并覆盖registerAuthentication
,它将使用传入的AuthenticationManagerBuilder
。这允许以与AuthenticationManager
WebSecurityConfigurerAdapter
。AuthenticationManagerBuilder
的全局共享实例中进行构建,如果失败,它将记录您所看到的错误消息(请注意,日志还指出“现在可以,我们将尝试直接使用AuthenticationManager”)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();
}
}
}
注意:有关此问题的更多文档将在 future 几天内添加到引用中。
关于java - Java配置和Spring Security 3.2的安全性方法注释,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19353578/