Два разных менеджера аутентификации для двух разных диспетчеров Servlet
В моем web.xml у меня есть два разных сервлета диспетчера, один из них содержит все bean-компоненты из корневого контекста, второй сервлет диспетчера имеет другой аутентификационный менеджер. как сказал:
В платформе Web MVC каждый DispatcherServlet имеет свой собственный WebApplicationContext, который наследует все bean-компоненты, уже определенные в корневом WebApplicationContext. Корневой WebApplicationContext должен содержать все инфраструктурные компоненты, которые должны совместно использоваться другими вашими контекстами и экземплярами сервлета. Эти унаследованные bean-компоненты могут быть переопределены в конкретной области сервлета, и вы можете определить новые bean-компоненты, зависящие от области, локально для данного экземпляра сервлета.
Так что мой новый authenticationManager должен переопределить тот же компонент из корневого контекста. У этого менеджера аутентификации есть еще один daoAuthenticationProvider, у которого есть еще один userDetailsService. Но когда я хочу войти в систему с пути для второго сервлета диспетчера, Spring использует authenticationManager из корневого контекста.
Это web.xml:
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>ua.translate.AppConfig</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>ua.translate.AppConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>adminDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>ua.admin.AdminConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>adminDispatcher</servlet-name>
<url-pattern>/bulbular/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Это AdminConfig.class:
@EnableWebMvc
@Configuration
@ComponentScan(basePackages = {"ua.admin"})
@EnableTransactionManagement
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AdminConfig extends WebMvcConfigurerAdapter{
}
Это реализация WebSecurityConfigurerAdapter, которая находится в пакете ua.admin и имеет новый аутентификационный менеджер:
@EnableWebSecurity
@Configuration
@ComponentScan(basePackages = {"ua.translate.handler","ua.translate.service.impl"})
@Order(1)
public class AdminSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
protected CustomSuccessHandler customSuccessHandler;
@Autowired
@Qualifier("customAccessDeniedHandler")
protected AccessDeniedHandler accessDeniedHandler;
@Autowired
@Qualifier("adminDetailsService")
private UserDetailsService uds;
@Override
public void configure(WebSecurity web){
web
.ignoring()
.antMatchers(new String[]{"/resources/**"});
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/bulbular/**")
.authorizeRequests()
.antMatchers("/bulbular/login").permitAll()
.anyRequest().hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/bulbular/login")
.permitAll()
.successHandler(customSuccessHandler)
.failureUrl("/bulbular/login?error")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/j_spring_security_check")
.and()
.logout().deleteCookies("JSESSIONID")
.logoutUrl("/bulbular/logout")
.logoutSuccessUrl("/bulbular/login?logout")
.and()
.csrf()
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler);
}
@Bean
public AuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider impl = new DaoAuthenticationProvider();
impl.setUserDetailsService(uds);
impl.setPasswordEncoder(bcryptEncoder());
impl.setHideUserNotFoundExceptions(false);
return impl;
}
@Bean
public PasswordEncoder bcryptEncoder(){
return new BCryptPasswordEncoder();
}
@Bean(name = "authenticationManager")
public ProviderManager getProviderManager(){
List<AuthenticationProvider> providers = new ArrayList<>();
providers.add(daoAuthenticationProvider());
ProviderManager providerManager = new ProviderManager(providers);
return providerManager;
}
Этот класс является реализацией WebSecurityConfigurer в корневом контексте, это базовый класс для двух других классов:
@EnableWebSecurity
@ComponentScan(basePackages = {"ua.translate"})
@Order(99)
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
protected CustomSuccessHandler customSuccessHandler;
@Autowired
@Qualifier("customAccessDeniedHandler")
protected AccessDeniedHandler accessDeniedHandler;
@Autowired
protected PersistentTokenRepository tokenRepository;
@Autowired
@Qualifier("userDetailsServiceImpl")
protected UserDetailsService uds;
@Override
public void configure(WebSecurity web){
web
.ignoring()
.antMatchers(new String[]{"/resources/**"});
}
@Bean
public AuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider impl = new DaoAuthenticationProvider();
impl.setUserDetailsService(uds);
impl.setPasswordEncoder(bcryptEncoder());
impl.setHideUserNotFoundExceptions(false);
return impl;
}
@Bean(name = "authenticationManager")
public ProviderManager getProviderManager(){
List<AuthenticationProvider> providers = new ArrayList<>();
providers.add(daoAuthenticationProvider());
ProviderManager providerManager = new ProviderManager(providers);
return providerManager;
}
@Bean
public PasswordEncoder bcryptEncoder(){
return new BCryptPasswordEncoder();
}
Есть два подкласса, которые расположены в корневом контексте:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Configuration
@Order(3)
public static class AppSecurityConfigClient extends AppSecurityConfig{
@Override
public void configure(WebSecurity web){
web
.ignoring()
.antMatchers(new String[]{"/resources/**"});
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/client/registration*").anonymous()
.antMatchers("/index","/translators","/orders","/client/login*","/client/confirmation").permitAll()
.antMatchers("/client/**").hasRole("CLIENT")
.and()
.formLogin()
.loginPage("/client/login")
.permitAll()
.successHandler(customSuccessHandler)
.failureUrl("/client/login?error")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/j_spring_security_check")
.and()
.logout().deleteCookies("JSESSIONID")
.logoutUrl("/client/logout")
.logoutSuccessUrl("/client/login?logout")
.and()
/*!!!!Доделать saved request url!!!!*/
.rememberMe().tokenRepository(tokenRepository)
.tokenValiditySeconds(86400)
.and()
.csrf()
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler);
}
}
@Configuration
@Order(2)
public static class AppSecurityConfigTranslator extends AppSecurityConfig {
@Override
public void configure(WebSecurity web){
web
.ignoring()
.antMatchers(new String[]{"/resources/**"});
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/translator/**")
.authorizeRequests()
.antMatchers("/translator/registration*").anonymous()
.antMatchers("/translator/index","/translator/login*","/translator/confirmation").permitAll()
.antMatchers("/translator/**").hasRole("TRANSLATOR")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/translator/login")
.permitAll()
.successHandler(customSuccessHandler)
.failureUrl("/translator/login?error")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/j_spring_security_check")
.and()
.logout().deleteCookies("JSESSIONID")
.logoutUrl("/translator/logout")
.logoutSuccessUrl("/translator/login?logout")
.and()
/**
* Доделать saved request url!!!
*/
.rememberMe().tokenRepository(tokenRepository)
.tokenValiditySeconds(86400)
.and()
.csrf()
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.and()
.userDetailsService(uds);
}
}
}
Так, сервлет adminDispatcher использует ua.admin.AdminConfig, который, в свою очередь, сканирует пакет ua.admin и находит реализацию WebSecurityConfigurerAdapter со второй реализацией authenticationManager.
/ bulbular / - это путь для этого сервлета диспетчера и путь для конфигурации http в реализации WebSecurityConfigurerAdapter. Но когда я хочу войти со страницы /bulbular/login, Spring использует реализацию из SecurityConfig.class - класс из корневого контекста. Помогите, пожалуйста!!!!