在我的web.xml中,我有两个不同的调度程序servlet,其中一个具有来自根上下文的所有bean,第二个调度程序servlet具有另一个authenticationManager。 如上所述:
在Web MVC框架中,每个DispatcherServlet 有自己的WebApplicationContext,它继承了root中已经定义的所有bean WebApplicationContext中。根WebApplicationContext应包含所有基础结构 应该在其他上下文和Servlet实例之间共享的bean。这些继承的bean 可以在特定于servlet的作用域中重写,并且可以在本地定义新的作用域特定的bean 给定的Servlet实例。
所以我的新authenticationManager必须从根上下文覆盖相同的bean。此authenticationManager具有另一个daoAuthenticationProvider,它具有另一个userDetailsService。但是当我想从第二个调度程序servlet的路径登录系统时,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实现,它是另外两个类的基类:
@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 servlet使用ua.admin.AdminConfig,它反过来扫描ua.admin包,并使用第二个authenticationManager实现找到WebSecurityConfigurerAdapter实现。
/ bulbular / - 它是此dispathcer servlet的路径,以及WebSecurityConfigurerAdapter实现中http配置的路径。但是当我想从/ bulbular / login页面登录时,spring使用来自SecurityConfig.class的实现 - 来自根上下文的类。请帮助!!!!