Yuriy
Yuriy

Reputation: 1442

Two different authenticationManagers for two different dispatcherServlet

In my web.xml I have two different dispatcher servlets, one of them has all beans from root context, second dispatcher servlet has another authenticationManager. as sayed:

In the Web MVC framework, each DispatcherServlet has its own WebApplicationContext, which inherits all the beans already defined in the root WebApplicationContext. The root WebApplicationContext should contain all the infrastructure beans that should be shared between your other contexts and Servlet instances. These inherited beans can be overridden in the servlet-specific scope, and you can define new scope-specific beans local to a given Servlet instance.

So my new authenticationManager must override the same bean from root context. This authenticationManager has another daoAuthenticationProvider, which has another userDetailsService. But when I want to log in in system from path for second dispathcer servlet, spring uses authenticationManager from root context.

It is 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>

It is AdminConfig.class:

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = {"ua.admin"})
@EnableTransactionManagement
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AdminConfig extends WebMvcConfigurerAdapter{
}

It is WebSecurityConfigurerAdapter implementation, which is located in ua.admin package and have new authenticationManager:

@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;

}

This class is WebSecurityConfigurer implementation in root context, it is base class for two another classes:

@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();
}

There are two subclasses, which is located in root context:

@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);
    }

}

}

So, adminDispatcher servlet uses ua.admin.AdminConfig, which in turn scan ua.admin package, and find WebSecurityConfigurerAdapter implementation with second authenticationManager implementation.

/bulbular/ - it is path for this dispathcer servlet, and path for http configuration in WebSecurityConfigurerAdapter implementation. But when I want to log in from /bulbular/login page, spring uses implementatation from SecurityConfig.class - class from root context. Help please!!!!

Upvotes: 0

Views: 57

Answers (0)

Related Questions