I am setting up an app with 2 differents users:
I created 2 Security configurations:
External User Configuration:
@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 Configuration:
@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;
}
Each configuration work when it's alone, but when there is both, the external doesn't work.
It seems that the CasAuthenticationProvider bean prevent the formLogin to work and I endup in the FailureHandler.
Here is the error:
org.springframework.security.authentication.ProviderNotFoundException: No AuthenticationProvider found for org.springframework.security.authentication.UsernamePasswordAuthenticationToken
How can I make these 2 configuration work together?
when you mark something as @Bean
you are putting it in the pool of beans that spring can use to inject into classes if they need it.
you have registered
@Bean
public CasAuthenticationProvider casAuthenticationProvider() {
...
}
as a @Bean
which is an AuthenticationProvider
. When you register this using @Bean
it will get picked up by everyone that needs it, meaning that both your WebSecurityConfigurerAdapter
will use it.
Spring has no way of knowing that you only want this is in one of your security configurations and not the other.
you have to explicitly define that you want it in one and not the other by removing @Bean
and setting it manually.
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(casAuthenticationProvider());
}
public CasAuthenticationProvider casAuthenticationProvider() {
...
}
You have to always decied if you want to set something manually, or use @Bean
and let spring inject it for you.
So for instance, you are registering a filter (casLogoutFilter) setting it manually but also defining it as @Bean
telling spring to inject it into the filter chain, which sort of doesn't make sense.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.