我正在为 2 个不同的用户设置一个应用:
我创建了 2 个安全配置:
外部用户配置:
@EnableWebSecurity
@Configuration
@RequiredArgsConstructor
@Order(1)
public class SecurityVanuatuConfiguration extends WebSecurityConfigurerAdapter {
@Bean
@Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withUsername("user")
.password("{noop}user")
.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
我怎样才能让这两个配置一起工作?
答案 0 :(得分: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 将其注入过滤器链,这有点没有意义。