私の web.xml には 2 つの異なるディスパッチャ サーブレットがあり、そのうちの 1 つはルート コンテキストからのすべての Bean を持ち、2 番目のディスパッチャ サーブレットには別の authenticationManager があります。言ったように:
Web MVC フレームワークでは、各 DispatcherServlet に独自の WebApplicationContext があり、ルート WebApplicationContext で既に定義されているすべての Bean を継承します。ルート WebApplicationContext には、他のコンテキストとサーブレット インスタンス間で共有する必要があるすべてのインフラストラクチャ Bean が含まれている必要があります。これらの継承された Bean は、サーブレット固有のスコープでオーバーライドでき、特定のサーブレット インスタンスに対してローカルな新しいスコープ固有の Bean を定義できます。
したがって、私の新しい authenticationManager は、ルート コンテキストから同じ Bean をオーバーライドする必要があります。この authenticationManager には、別の userDetailsService を持つ別の daoAuthenticationProvider があります。しかし、2 番目の dispathcer サーブレットのパスからシステムにログインする場合、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 パッケージにあり、新しい 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;
}
このクラスは、ルート コンテキストでの WebSecurityConfigurer 実装であり、別の 2 つのクラスの基本クラスです。
@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();
}
ルート コンテキストにある 2 つのサブクラスがあります。
@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 パッケージをスキャンして、2 番目の authenticationManager 実装を持つ WebSecurityConfigurerAdapter 実装を見つけます。
/bulbular/ - これは、この dispathcer サーブレットのパスであり、WebSecurityConfigurerAdapter 実装の http 構成のパスです。しかし、/bulbular/login ページからログインする場合、Spring は SecurityConfig.class (ルート コンテキストのクラス) からの実装を使用します。助けてください!!!!