具有多个提供程序的 Spring 安全性
Posted
技术标签:
【中文标题】具有多个提供程序的 Spring 安全性【英文标题】:Spring security with multiple providers 【发布时间】:2021-06-01 14:15:39 【问题描述】:我正在设置一个包含 2 个不同用户的应用:
我的 ldap 中可以连接 cas 身份验证的一个 一个外部硬编码,使用简单的表单登录我创建了 2 个安全配置:
外部用户配置:
@EnableWebSecurity
@Configuration
@RequiredArgsConstructor
@Order(1)
public class SecurityVanuatuConfiguration extends WebSecurityConfigurerAdapter
@Bean
@Override
public UserDetailsService userDetailsService()
UserDetails user =
User.withUsername("user")
.password("noopuser")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
@Override
protected void configure(HttpSecurity http) throws Exception
http
.csrf().disable().antMatcher("/user/**")
.authorizeRequests()
.requestMatchers(SecurityUtils::isFrameworkInternalRequest).permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage(LOGIN_URL).permitAll()
.loginProcessingUrl(LOGIN_PROCESSING_URL)
.failureUrl(LOGIN_FAILURE_URL)
.successHandler(successHandler)
.failureHandler(successHandler)
.and().logout().logoutSuccessUrl(LOGOUT_SUCCESS_URL);
Cas 配置:
@EnableWebSecurity
@Configuration
@RequiredArgsConstructor
@Order(2)
public class SecurityCasConfiguration extends WebSecurityConfigurerAdapter
@Override
protected void configure(HttpSecurity http) throws Exception
http.csrf().disable().antMatcher("/admin/**")
.authorizeRequests()
.requestMatchers(SecurityUtils::isFrameworkInternalRequest).permitAll()
.anyRequest().authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint())
.and()
.addFilter(casAuthenticationFilter())
.addFilterBefore(casLogoutFilter(), CasAuthenticationFilter.class);
@Bean
public SingleSignOutFilter casLogoutFilter()
SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
return singleSignOutFilter;
// if I remove this bean, external configuration works
@Bean
public CasAuthenticationProvider casAuthenticationProvider()
CasAuthenticationProvider provider = new CasAuthenticationProvider();
provider.setServiceProperties(serviceProperties());
provider.setTicketValidator(new Cas30ServiceTicketValidator("https://sso.unc.nc/cas"));
provider.setKey("cas");
provider.setAuthenticationUserDetailsService(successHandler);
return provider;
单独配置时,每个配置都有效,但同时存在时,外部不起作用。
似乎 CasAuthenticationProvider bean 阻止了 formLogin 工作,我最终进入了 FailureHandler。
这是错误:
org.springframework.security.authentication.ProviderNotFoundException: No AuthenticationProvider found for org.springframework.security.authentication.UsernamePasswordAuthenticationToken
我怎样才能让这两个配置一起工作?
【问题讨论】:
【参考方案1】:当您将某些内容标记为@Bean
时,您就是将其放入了 bean 池中,spring 可以在需要时将其注入到类中。
你已经注册了
@Bean
public CasAuthenticationProvider casAuthenticationProvider()
...
作为@Bean
,即AuthenticationProvider
。当您使用 @Bean
注册时,所有需要它的人都会收到它,这意味着您的 WebSecurityConfigurerAdapter
都会使用它。
Spring 无法知道您只希望这是在您的一种安全配置中,而不是另一种。
您必须通过删除 @Bean
并手动设置来明确定义您想要它在一个而不是另一个。
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.authenticationProvider(casAuthenticationProvider());
public CasAuthenticationProvider casAuthenticationProvider()
...
您必须始终决定是否要手动设置某些内容,或者使用 @Bean
并让 spring 为您注入。
因此,例如,您正在注册一个过滤器 (casLogoutFilter) 手动设置它,但也将其定义为 @Bean
告诉 spring 将其注入过滤器链,这没有任何意义。
【讨论】:
以上是关于具有多个提供程序的 Spring 安全性的主要内容,如果未能解决你的问题,请参考以下文章
防止 Spring Security 通过下一个身份验证提供程序对具有 BadCredentialException 的用户进行身份验证
Spring-boot 安全性不会尊重具有自定义 AuthenticationProvider 的角色 [重复]
特定 url 的多个身份验证提供程序 - Spring Boot Security
Spring Security 具有不同用户详细信息的多个 HTTPSecurity 服务在 Spring Boot 中不起作用
具有多个 DispatcherServlet 的 Spring Boot,每个 DispatcherServlet 都有自己的 @Controller