使用具有不同 AuthenticationProviders 的多个 WebSecurityConfigurerAdapter(API 的基本身份验证和 Web 应用程序的 LDAP) [英] Using multiple WebSecurityConfigurerAdapter with different AuthenticationProviders (basic auth for API and LDAP for web app)
问题描述
根据 Spring 安全参考第 5.7 节 应该可以定义多个安全适配器.
我也尝试这样做,但没有成功.服务器重新启动后,前 x 次 API 可以正常使用基本身份验证,但几次后我被重定向到登录(表单)页面,这应该只发生在我们的 Web 应用程序中,而不是 API 调用中.
我的代码:
@EnableWebSecurity公共类 MultiHttpSecurityConfig {@配置@订单(1)公共静态类 ApiWebSecurityConfigurationAdapter 扩展了 WebSecurityConfigurerAdapter {@自动连线私人环境环境;@自动连线public void configureGlobal(AuthenticationManagerBuilder auth) 抛出异常 {auth.inMemoryAuthentication().withUser("admin").password("pw_test").roles(API_ROLE);}protected void configure(HttpSecurity http) 抛出异常 {http.antMatcher("/services/**").authorizeRequests().anyRequest().hasRole(API_ROLE).和().httpBasic().和().csrf().disable();}}@配置@订单(2)公共静态类 FormLoginWebSecurityConfigurerAdapter 扩展 WebSecurityConfigurerAdapter {@自动连线私人环境环境;@自动连线public void configureGlobal(AuthenticationManagerBuilder auth) 抛出异常 {auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());auth.eraseCredentials(false);}@覆盖protected void configure(HttpSecurity http) 抛出异常 {//LDAP 表单认证http.authorizeRequests().antMatchers("/login.html").permitAll().antMatchers("/css/**").permitAll().antMatchers("/js/**").permitAll().antMatchers("/images/**").permitAll().anyRequest().authenticated().and().formLogin().failureUrl("/login.html?error=1").loginPage("/login.html").loginProcessingUrl("/j_spring_security_check").defaultSuccessUrl("/success.html").usernameParameter("j_username").passwordParameter("j_password").permitAll();http.csrf().disable();//iFRAMES 设置http.headers().frameOptions().sameOrigin().httpStrictTransportSecurity().disable();//HTTPShttp.requiresChannel().anyRequest().requiresSecure();//将8080映射到HTTPS端口http.portMapper().http(8080).mapsTo(443);}@豆角,扁豆公共 AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {CustomLdapAuthenticationProvider provider = new CustomLdapAuthenticationProvider(env.getProperty("ldap.domain"), env.getProperty("ldap.url"), env.getProperty("ldap.base"));provider.setConvertSubErrorCodesToExceptions(true);provider.setUseAuthenticationRequestCredentials(true);返回提供者;}}}
有什么想法吗?
我使用的是 Spring Boot 版本 1.4.1-RELEASE 和 Spring Security 版本 4.1.3-RELEASE.
你用同样的 AuthenticationManager
用于两种配置,因为您自动装配相同的 AuthenticationManagerBuilder
.
参见 Spring 安全架构:
<块引用>@Configuration公共类 ApplicationSecurity 扩展了 WebSecurityConfigurerAdapter {...//这里的网络内容@自动连线公共无效初始化(AuthenticationManagerBuilder 构建器,数据源数据源){builder.jdbcAuthentication().dataSource(dataSource).withUser("dave").password("secret").roles("USER");}}
此示例与 Web 应用程序相关,但 AuthenticationManagerBuilder
的用法适用范围更广(有关如何实现 Web 应用程序安全性的更多详细信息,请参见下文).请注意,AuthenticationManagerBuilder
是 @Autowired
到 @Bean
中的一个方法 - 这就是它构建全局(父)AuthenticationManager 的原因.相反,如果我们这样做:
@Configuration公共类 ApplicationSecurity 扩展了 WebSecurityConfigurerAdapter {@自动连线数据源数据源;...//这里的网络内容@覆盖公共无效配置(AuthenticationManagerBuilder 构建器){builder.jdbcAuthentication().dataSource(dataSource).withUser("dave").password("secret").roles("USER");}}
(在配置器中使用一个方法的 @Override
)那么 AuthenticationManagerBuilder
仅用于构建本地"AuthenticationManager
,这是全局的孩子.
According the Spring Security Reference section 5.7 it should be possible to define more than one security adapter.
I try to do the same but without success. After a server reboot, the first x times the API works fine with basic auth, but after a couple of times I'm redirected to the login (form) page, this should only happen for our web app, not for the API calls.
My code:
@EnableWebSecurity
public class MultiHttpSecurityConfig {
@Configuration
@Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private Environment env;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().
withUser("admin").password("pw_test").roles(API_ROLE);
}
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/services/**")
.authorizeRequests()
.anyRequest().hasRole(API_ROLE)
.and()
.httpBasic()
.and()
.csrf()
.disable();
}
}
@Configuration
@Order(2)
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private Environment env;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
auth.eraseCredentials(false);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// LDAP FORM AUTHENTICATION
http.authorizeRequests()
.antMatchers("/login.html").permitAll()
.antMatchers("/css/**").permitAll()
.antMatchers("/js/**").permitAll()
.antMatchers("/images/**").permitAll()
.anyRequest().authenticated()
.and().formLogin()
.failureUrl("/login.html?error=1")
.loginPage("/login.html")
.loginProcessingUrl("/j_spring_security_check")
.defaultSuccessUrl("/success.html")
.usernameParameter("j_username")
.passwordParameter("j_password")
.permitAll();
http.csrf().disable();
// iFRAMES SETTINGS
http
.headers()
.frameOptions().sameOrigin()
.httpStrictTransportSecurity().disable();
// HTTPS
http
.requiresChannel()
.anyRequest()
.requiresSecure();
//MAP 8080 to HTTPS PORT
http.portMapper().http(8080).mapsTo(443);
}
@Bean
public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
CustomLdapAuthenticationProvider provider = new CustomLdapAuthenticationProvider(env.getProperty("ldap.domain"), env.getProperty("ldap.url"), env.getProperty("ldap.base"));
provider.setConvertSubErrorCodesToExceptions(true);
provider.setUseAuthenticationRequestCredentials(true);
return provider;
}
}
}
Any idea?
I'm using Spring Boot version 1.4.1-RELEASE and Spring Security version 4.1.3-RELEASE.
You use the same AuthenticationManager
for both configurations, because you autowire the same AuthenticationManagerBuilder
.
See Spring Security Architecture:
@Configuration public class ApplicationSecurity extends WebSecurityConfigurerAdapter { ... // web stuff here @Autowired public void initialize(AuthenticationManagerBuilder builder, DataSource dataSource) { builder.jdbcAuthentication().dataSource(dataSource).withUser("dave") .password("secret").roles("USER"); } }
This example relates to a web application, but the usage of
AuthenticationManagerBuilder
is more widely applicable (see below for more detail on how web application security is implemented). Note that theAuthenticationManagerBuilder
is@Autowired
into a method in a@Bean
- that is what makes it build the global (parent) AuthenticationManager. In contrast if we had done it this way:@Configuration public class ApplicationSecurity extends WebSecurityConfigurerAdapter { @Autowired DataSource dataSource; ... // web stuff here @Override public void configure(AuthenticationManagerBuilder builder) { builder.jdbcAuthentication().dataSource(dataSource).withUser("dave") .password("secret").roles("USER"); } }
(using an
@Override
of a method in the configurer) then theAuthenticationManagerBuilder
is only used to build a "local"AuthenticationManager
, which is a child of the global one.
这篇关于使用具有不同 AuthenticationProviders 的多个 WebSecurityConfigurerAdapter(API 的基本身份验证和 Web 应用程序的 LDAP)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!